diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index d4a41ea1a0..92b071e35a 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -334,15 +334,7 @@ public function specifyTypesInCondition( && isset($exprNode->getArgs()[0]) && $constantType instanceof ConstantStringType ) { - return $this->specifyTypesInCondition( - $scope, - new Instanceof_( - $exprNode->getArgs()[0]->value, - new Name($constantType->getValue()), - ), - $context, - $rootExpr, - ); + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); } } @@ -1118,6 +1110,24 @@ private function specifyTypesForConstantStringBinaryExpression( } } + if ( + $context->true() + && $unwrappedExprNode instanceof FuncCall + && $unwrappedExprNode->name instanceof Name + && strtolower($unwrappedExprNode->name->toString()) === 'get_class' + && isset($unwrappedExprNode->getArgs()[0]) + ) { + return $this->specifyTypesInCondition( + $scope, + new Instanceof_( + $unwrappedExprNode->getArgs()[0]->value, + new Name($constantType->getValue()), + ), + $context, + $rootExpr, + )->unionWith($this->create($exprNode, $constantType, $context, false, $scope, $rootExpr)); + } + if ( $context->true() && $exprNode instanceof FuncCall diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index e47f09b201..9e13b40e29 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -193,8 +193,8 @@ public function dataCondition(): array ]), new String_('Foo'), ), - ['$foo' => 'Foo'], - ['$foo' => '~Foo'], + ['$foo' => 'Foo', 'get_class($foo)' => '\'Foo\''], + ['get_class($foo)' => '~\'Foo\''], ], [ new Equal( @@ -203,8 +203,8 @@ public function dataCondition(): array new Arg(new Variable('foo')), ]), ), - ['$foo' => 'Foo'], - ['$foo' => '~Foo'], + ['$foo' => 'Foo', 'get_class($foo)' => '\'Foo\''], + ['get_class($foo)' => '~\'Foo\''], ], [ new BooleanNot( diff --git a/tests/PHPStan/Analyser/data/match-expr.php b/tests/PHPStan/Analyser/data/match-expr.php index fa67613139..7aff6cebdf 100644 --- a/tests/PHPStan/Analyser/data/match-expr.php +++ b/tests/PHPStan/Analyser/data/match-expr.php @@ -2,6 +2,7 @@ namespace MatchExpr; +use function get_class; use function PHPStan\Testing\assertType; class Foo @@ -77,3 +78,26 @@ public function doGettype(int|float|bool|string|object|array $value): void } } + +final class FinalFoo +{ + +} + +final class FinalBar +{ + +} + +class TestGetClass +{ + + public function doMatch(FinalFoo|FinalBar $class): void + { + match (get_class($class)) { + FinalFoo::class => assertType(FinalFoo::class, $class), + FinalBar::class => assertType(FinalBar::class, $class), + }; + } + +} diff --git a/tests/PHPStan/Rules/Comparison/data/match-expr.php b/tests/PHPStan/Rules/Comparison/data/match-expr.php index e70f3a7fe3..37d5e01c1e 100644 --- a/tests/PHPStan/Rules/Comparison/data/match-expr.php +++ b/tests/PHPStan/Rules/Comparison/data/match-expr.php @@ -180,3 +180,26 @@ function (): string { -1 => 'down', }; }; + +final class FinalFoo +{ + +} + +final class FinalBar +{ + +} + +class TestGetClass +{ + + public function doMatch(FinalFoo|FinalBar $class): void + { + match (get_class($class)) { + FinalFoo::class => 1, + FinalBar::class => 2, + }; + } + +}