diff --git a/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php b/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php index 29b0801ece..9033aa3865 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php @@ -8,6 +8,7 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use function sprintf; +use function strtolower; /** * @implements Rule @@ -37,6 +38,9 @@ public function processNode(Node $node, Scope $scope): array } $functionName = (string) $node->name; + if (strtolower($functionName) === 'is_a') { + return []; + } $isAlways = $this->impossibleCheckTypeHelper->findSpecifiedType($scope, $node); if ($isAlways === null) { return []; diff --git a/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php index 4d062efd56..c4000b9aff 100644 --- a/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php @@ -9,12 +9,9 @@ use PHPStan\Analyser\TypeSpecifierAwareExtension; use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Type\ClassStringType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\FunctionTypeSpecifyingExtension; -use PHPStan\Type\ObjectWithoutClassType; -use PHPStan\Type\TypeCombinator; use function count; use function strtolower; @@ -50,20 +47,9 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $allowStringType = isset($node->getArgs()[2]) ? $scope->getType($node->getArgs()[2]->value) : new ConstantBooleanType(false); $allowString = !$allowStringType->equals(new ConstantBooleanType(false)); - $superType = $allowString - ? TypeCombinator::union(new ObjectWithoutClassType(), new ClassStringType()) - : new ObjectWithoutClassType(); - - $resultType = $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, true); - - // prevent false-positives in IsAFunctionTypeSpecifyingHelper - if ($resultType->equals($superType) && $resultType->isSuperTypeOf($objectOrClassType)->yes()) { - return new SpecifiedTypes([], []); - } - return $this->typeSpecifier->create( $node->getArgs()[0]->value, - $resultType, + $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, true), $context, false, $scope, diff --git a/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php index 0ca6cf4e76..2d52ee99e1 100644 --- a/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php @@ -9,12 +9,9 @@ use PHPStan\Analyser\TypeSpecifierAwareExtension; use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Type\ClassStringType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\FunctionTypeSpecifyingExtension; use PHPStan\Type\Generic\GenericClassStringType; -use PHPStan\Type\ObjectWithoutClassType; -use PHPStan\Type\TypeCombinator; use function count; use function strtolower; @@ -51,20 +48,9 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n return new SpecifiedTypes([], []); } - $superType = $allowString - ? TypeCombinator::union(new ObjectWithoutClassType(), new ClassStringType()) - : new ObjectWithoutClassType(); - - $resultType = $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, false); - - // prevent false-positives in IsAFunctionTypeSpecifyingHelper - if ($resultType->equals($superType) && $resultType->isSuperTypeOf($objectOrClassType)->yes()) { - return new SpecifiedTypes([], []); - } - return $this->typeSpecifier->create( $node->getArgs()[0]->value, - $resultType, + $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, false), $context, false, $scope, diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index 4ad6a7cec4..999c7169a3 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -1133,7 +1133,9 @@ public function dataCondition(): iterable new Arg(new Variable('stringOrNull')), new Arg(new Expr\ConstFetch(new Name('false'))), ]), - [], + [ + '$object' => 'object', + ], [], ], [ diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index b15cf528b0..16529f3a74 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -1102,11 +1102,4 @@ public function testAlwaysTruePregMatch(): void $this->analyse([__DIR__ . '/data/always-true-preg-match.php'], []); } - public function testBug3979(): void - { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/bug-3979.php'], []); - } - } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-3979.php b/tests/PHPStan/Rules/Comparison/data/bug-3979.php deleted file mode 100644 index f0f21220d1..0000000000 --- a/tests/PHPStan/Rules/Comparison/data/bug-3979.php +++ /dev/null @@ -1,130 +0,0 @@ -