diff --git a/build/composer-dependency-analyser.php b/build/composer-dependency-analyser.php index 5797d95bcf..e3d062ced1 100644 --- a/build/composer-dependency-analyser.php +++ b/build/composer-dependency-analyser.php @@ -33,6 +33,7 @@ ) ->ignoreErrorsOnPackage('phpunit/phpunit', [ErrorType::DEV_DEPENDENCY_IN_PROD]) // prepared test tooling ->ignoreErrorsOnPackage('jetbrains/phpstorm-stubs', [ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV]) // there is no direct usage, but we need newer version then required by ondrejmirtes/BetterReflection + ->ignoreErrorsOnPackage('composer/pcre', [ErrorType::SHADOW_DEPENDENCY]) // reverse dependency on composer/pcre to support https://github.com/composer/pcre/pull/24 ->ignoreErrorsOnPath(__DIR__ . '/../tests', [ErrorType::UNKNOWN_CLASS, ErrorType::UNKNOWN_FUNCTION]) // to be able to test invalid symbols ->ignoreUnknownClasses([ 'JetBrains\PhpStorm\Pure', // not present on composer's classmap diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 4115a752e0..c3ae733ae3 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -2,6 +2,7 @@ namespace PHPStan\Analyser; +use Composer\Pcre\Preg; use Countable; use PhpParser\Node; use PhpParser\Node\Expr; @@ -1911,6 +1912,18 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif ) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); } + + if ( + $context->true() + && $exprNode instanceof StaticCall + && $exprNode->class instanceof Name + && $exprNode->class->toString() === Preg::class + && $exprNode->name instanceof Node\Identifier + && $exprNode->name->toLowerString() === 'match' + && (new ConstantIntegerType(1))->isSuperTypeOf($constantType)->yes() + ) { + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); + } } $leftType = $scope->getType($expr->left); @@ -2015,6 +2028,23 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty ); } + if ( + $context->true() + && $unwrappedLeftExpr instanceof StaticCall + && $unwrappedLeftExpr->class instanceof Name + && $unwrappedLeftExpr->class->toString() === Preg::class + && $unwrappedLeftExpr->name instanceof Node\Identifier + && $unwrappedLeftExpr->name->toLowerString() === 'match' + && (new ConstantIntegerType(1))->isSuperTypeOf($rightType)->yes() + ) { + return $this->specifyTypesInCondition( + $scope, + $leftExpr, + $context, + $rootExpr, + ); + } + if ( $context->true() && $unwrappedLeftExpr instanceof FuncCall