Skip to content

Commit 425d028

Browse files
committed
Fix invokable objects incorrectly labeled as instances of Closure
1 parent 6d92b33 commit 425d028

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

src/Type/Accessory/HasMethodType.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Accessory;
44

5+
use Closure;
56
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
67
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
78
use PHPStan\Reflection\ClassMemberAccessAnswerer;
@@ -17,6 +18,7 @@
1718
use PHPStan\Type\ErrorType;
1819
use PHPStan\Type\IntersectionType;
1920
use PHPStan\Type\IsSuperTypeOfResult;
21+
use PHPStan\Type\ObjectType;
2022
use PHPStan\Type\StringType;
2123
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
2224
use PHPStan\Type\Traits\NonGenericTypeTrait;
@@ -83,7 +85,11 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult
8385
return $otherType->isSuperTypeOf($this);
8486
}
8587

86-
if ($this->isCallable()->yes() && $otherType->isCallable()->yes()) {
88+
if (
89+
$this->isCallable()->yes()
90+
&& $otherType->isCallable()->yes()
91+
&& (new ObjectType(Closure::class))->isSuperTypeOf($otherType)->no()
92+
) {
8793
return IsSuperTypeOfResult::createYes();
8894
}
8995

tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,4 +569,10 @@ public function testBug13469(): void
569569
]);
570570
}
571571

572+
public function testBug13975(): void
573+
{
574+
$this->treatPhpDocTypesAsCertain = true;
575+
$this->analyse([__DIR__ . '/data/bug-13975.php'], []);
576+
}
577+
572578
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Bug13975;
4+
5+
function foo(): callable
6+
{
7+
return new class () {
8+
public function __invoke(): void
9+
{
10+
}
11+
};
12+
}
13+
14+
$foo = foo();
15+
16+
if (\is_object($foo) && method_exists($foo, '__invoke') && !$foo instanceof \Closure) {
17+
echo 'true';
18+
}

0 commit comments

Comments
 (0)