This document is a work in progress.
PHPStan now requires PHP 7.4 or newer to run.
The best way do get ready for upgrade to PHPStan 2.0 is to update to the latest PHPStan 1.12 release and enable Bleeding Edge. This will enable the new rules and behaviours that 2.0 turns on for all users.
Also make sure to install and enable phpstan/phpstan-deprecation-rules.
Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in composer.json:
"require-dev": {
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-doctrine": "^2.0",
"phpstan/phpstan-nette": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-symfony": "^2.0",
"phpstan/phpstan-webmozart-assert": "^2.0",
...
}Don't forget to update 3rd party PHPStan extensions as well.
After changing your composer.json, run composer update 'phpstan/*' -W.
It's up to you whether you go through the new reported errors or if you just put them all to the baseline ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0.
It's strongly recommended to add the missing array typehints.
If you want to continue ignoring missing typehints from arrays, add missingType.iterableValue error identifier to your ignoreErrors:
parameters:
ignoreErrors:
-
identifier: missingType.iterableValueIt's strongly recommended to add the missing generic typehints.
If you want to continue ignoring missing typehints from generics, add missingType.generics error identifier to your ignoreErrors:
parameters:
ignoreErrors:
-
identifier: missingType.genericsThese options have been removed because PHPStan now always behaves as if these were set to true:
checkAlwaysTrueCheckTypeFunctionCallcheckAlwaysTrueInstanceofcheckAlwaysTrueStrictComparisoncheckAlwaysTrueLooseComparison
It has been replaced with excludePaths.
If you are excluding a file path that might not exist but you still want to have it in excludePaths, append (?):
parameters:
excludePaths:
- tests/*/data/*
- src/broken
- node_modules (?) # optional path, might not existIf you have the same situation in ignoreErrors (ignoring an error in a path that might not exist), use reportUnmatchedIgnoredErrors: false.
parameters:
reportUnmatchedIgnoredErrors: falseAppending (?) in ignoreErrors is not supported.
- Removed unused config parameter
cache.nodesByFileCountMax - Removed unused config parameter
memoryLimitFile - Removed unused feature toggle
disableRuntimeReflectionProvider
See UPGRADING guide for PHP-Parser.
The most notable change is how throw statement is represented. Previously, throw statements like throw $e; were represented using the Stmt\Throw_ class, while uses inside other expressions (such as $x ?? throw $e) used the Expr\Throw_ class.
Now, throw $e; is represented as a Stmt\Expression that contains an Expr\Throw_. The
Stmt\Throw_ class has been removed.
See UPGRADING guide for phpstan/phpdoc-parser.
Identifiers are also required in custom rules.
Learn more: Using RuleErrorBuilder to enrich reported errors in custom rules
Before:
return ['My error'];After:
return [
RuleErrorBuilder::mesage('My error')
->identifier('my.error')
->build(),
];Learn more: Why Is instanceof *Type Wrong and Getting Deprecated?
PHPStan\Analyser\TypeSpecifier::create() now accepts (all parameters are required):
Expr $exprType $typeTypeSpecifierContext $contextScope $scope
If you want to change $overwrite or $rootExpr (previous parameters also used to be accepted by this method), call setAlwaysOverwriteTypes() and setRootExpr() on SpecifiedTypes (object returned by TypeSpecifier::create()). These methods return a new object (SpecifiedTypes is immutable).
SpecifiedTypes constructor now accepts:
array $sureTypesarray $sureNotTypes
If you want to change $overwrite or $rootExpr (previous parameters also used to be accepted by the constructor), call setAlwaysOverwriteTypes() and setRootExpr(). These methods return a new object (SpecifiedTypes is immutable).
This method now longer accepts Expr $rootExpr. If you want to change it, call setRootExpr() on SpecifiedTypes (object returned by TypeSpecifier::specifyTypesInCondition()). setRootExpr() method returns a new object (SpecifiedTypes is immutable).
Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules
As a replacement you can implement PHPStan\Type\ExpressionTypeResolverExtension interface instead and register it as a service.
- Parameter
$callableParametersofMutatingScope::enterAnonymousFunction()andenterArrowFunction()made required - Parameter
StatementContext $contextofNodeScopeResolver::processStmtNodes()made required - ClassPropertiesNode - remove
$extensionsparameter fromgetUninitializedProperties() Type::getSmallerType(),Type::getSmallerOrEqualType(),Type::getGreaterType(),Type::getGreaterOrEqualType(),Type::isSmallerThan(),Type::isSmallerThanOrEqual()now requirePhpVersionas argument.CompoundType::isGreaterThan(),CompoundType::isGreaterThanOrEqual()now requirePhpVersionas argument.