diff --git a/src/Rule/ForbidIdenticalClassComparisonRule.php b/src/Rule/ForbidIdenticalClassComparisonRule.php index 303b09f..203152a 100644 --- a/src/Rule/ForbidIdenticalClassComparisonRule.php +++ b/src/Rule/ForbidIdenticalClassComparisonRule.php @@ -11,6 +11,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; +use PHPStan\Type\CallableType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; @@ -25,6 +26,11 @@ class ForbidIdenticalClassComparisonRule implements Rule { private const DEFAULT_BLACKLIST = [DateTimeInterface::class]; + private const IGNORED_TYPES = [ + MixedType::class, // mixed is "maybe" accepted by any (denied) class + ObjectWithoutClassType::class, // object is "maybe" accepted by any (denied) class + CallableType::class, // any non-final class descendant can have __invoke method causing it to be "maybe" accepted by any (denied) class + ]; /** * @var array> @@ -75,13 +81,10 @@ public function processNode(Node $node, Scope $scope): array return []; // always-true or always-false, already reported by native PHPStan (like $a === $a) } - if ( - $leftType instanceof MixedType - || $leftType instanceof ObjectWithoutClassType - || $rightType instanceof MixedType - || $rightType instanceof ObjectWithoutClassType - ) { - return []; // those may contain forbidden class, but that is too strict + foreach (self::IGNORED_TYPES as $ignoredType) { + if ($leftType instanceof $ignoredType || $rightType instanceof $ignoredType) { + return []; + } } $errors = []; diff --git a/tests/Rule/data/ForbidIdenticalClassComparisonRule/code.php b/tests/Rule/data/ForbidIdenticalClassComparisonRule/code.php index 174da65..0b99969 100644 --- a/tests/Rule/data/ForbidIdenticalClassComparisonRule/code.php +++ b/tests/Rule/data/ForbidIdenticalClassComparisonRule/code.php @@ -23,14 +23,16 @@ public function testNonObject(?DateTimeImmutable $a, string $b): void } } - public function testMixed(DateTimeImmutable $a, mixed $b): void - { - $a === $b; - } - - public function testAnyObject(DateTimeImmutable $a, object $b): void + public function testProblematicTypes( + DateTimeImmutable $a, + mixed $b, + object $c, + callable $d + ): void { $a === $b; + $a === $c; + $a === $d; } public function testRegular(DateTimeImmutable $a, DateTimeImmutable $b): void