diff --git a/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php index 4d062efd56..55789676aa 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,14 +47,10 @@ 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()) { + if ($classType->getConstantStrings() === [] && $resultType->isSuperTypeOf($objectOrClassType)->yes()) { return new SpecifiedTypes([], []); } diff --git a/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php index 0ca6cf4e76..71800c5366 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,14 +48,10 @@ 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()) { + if ($classType->getConstantStrings() === [] && $resultType->isSuperTypeOf($objectOrClassType)->yes()) { return new SpecifiedTypes([], []); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 896173a6ee..3236b7feee 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -1127,4 +1127,16 @@ public function testBug8954(): void $this->analyse([__DIR__ . '/data/bug-8954.php'], []); } + public function testBugPR3404(): void + { + $this->checkAlwaysTrueCheckTypeFunctionCall = true; + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-pr-3404.php'], [ + [ + 'Call to function is_a() with arguments BugPR3404\Location, \'BugPR3404\\\\Location\' and true will always evaluate to true.', + 21, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-pr-3404.php b/tests/PHPStan/Rules/Comparison/data/bug-pr-3404.php new file mode 100644 index 0000000000..7dd533ff98 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-pr-3404.php @@ -0,0 +1,24 @@ += 8.0 + +namespace BugPR3404; + +interface Location +{ + +} + +/** @return class-string */ +function aaa(): string +{ + +} + +function (Location $l): void { + if (is_a($l, aaa(), true)) { + // might not always be true. $l might be one subtype of Location, aaa() might return a name of a different subtype of Location + } + + if (is_a($l, Location::class, true)) { + // always true + } +};