diff --git a/src/Type/Accessory/HasMethodType.php b/src/Type/Accessory/HasMethodType.php index 66d8365595..7d3901cc51 100644 --- a/src/Type/Accessory/HasMethodType.php +++ b/src/Type/Accessory/HasMethodType.php @@ -2,6 +2,7 @@ namespace PHPStan\Type\Accessory; +use Closure; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\ClassMemberAccessAnswerer; @@ -83,7 +84,11 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - if ($this->isCallable()->yes() && $otherType->isCallable()->yes()) { + if ( + $this->isCallable()->yes() + && $otherType->isCallable()->yes() + && !($otherType->isObject()->yes() && $otherType->isInstanceOf(Closure::class)->yes()) + ) { return IsSuperTypeOfResult::createYes(); } diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 413d8f160d..25f31d9158 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1619,6 +1619,12 @@ public function testBug13980(): void $this->assertNoErrors($errors); } + public function testBug13975(): void + { + $errors = $this->runAnalyse(__DIR__ . '/data/bug-13975.php'); + $this->assertNoErrors($errors); + } + /** * @param string[]|null $allAnalysedFiles * @return list diff --git a/tests/PHPStan/Analyser/data/bug-13975.php b/tests/PHPStan/Analyser/data/bug-13975.php new file mode 100644 index 0000000000..69bfdd9ec0 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-13975.php @@ -0,0 +1,18 @@ +