Skip to content

Commit

Permalink
Fix interface accepting a Closure
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 7, 2023
1 parent cfb784a commit 0dbe3ab
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/Type/ObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ public function isSuperTypeOf(Type $type): TrinaryLogic
return self::$superTypes[$thisDescription][$description] = $type->isSubTypeOf($this);
}

if ($type instanceof ClosureType) {
return self::$superTypes[$thisDescription][$description] = $this->isInstanceOf(Closure::class);
}

if ($type instanceof ObjectWithoutClassType) {
if ($type->getSubtractedType() !== null) {
$isSuperType = $type->getSubtractedType()->isSuperTypeOf($this);
Expand Down Expand Up @@ -1289,6 +1293,14 @@ public function isInstanceOf(string $className): TrinaryLogic
return TrinaryLogic::createYes();
}

$reflectionProvider = ReflectionProviderStaticAccessor::getInstance();
if ($reflectionProvider->hasClass($className)) {
$thatClassReflection = $reflectionProvider->getClass($className);
if ($thatClassReflection->isFinal()) {
return TrinaryLogic::createNo();
}
}

if ($classReflection->isInterface()) {
return TrinaryLogic::createMaybe();
}
Expand Down
21 changes: 21 additions & 0 deletions tests/PHPStan/Type/ObjectTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use ArrayAccess;
use ArrayObject;
use Bug8850\UserInSessionInRoleEndpointExtension;
use Bug9006\TestInterface;
use Closure;
use Countable;
use DateInterval;
Expand Down Expand Up @@ -438,6 +439,16 @@ public function dataIsSuperTypeOf(): array
new ThisType($reflectionProvider->getClass(UserInSessionInRoleEndpointExtension::class)),
TrinaryLogic::createYes(),
],
62 => [
new ObjectType(TestInterface::class),
new ClosureType([], new MixedType(), false),
TrinaryLogic::createNo(),
],
63 => [
new ObjectType(TestInterface::class),
new ObjectType(Closure::class),
TrinaryLogic::createNo(),
],
];
}

Expand Down Expand Up @@ -492,6 +503,16 @@ public function dataAccepts(): array
),
TrinaryLogic::createNo(),
],
[
new ObjectType(TestInterface::class),
new ClosureType([], new MixedType(), false),
TrinaryLogic::createNo(),
],
63 => [
new ObjectType(TestInterface::class),
new ObjectType(Closure::class),
TrinaryLogic::createNo(),
],
];
}

Expand Down
33 changes: 33 additions & 0 deletions tests/PHPStan/Type/TypeCombinatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Type;

use Bug9006\TestInterface;
use CheckTypeFunctionCall\FinalClassWithMethodExists;
use CheckTypeFunctionCall\FinalClassWithPropertyExists;
use Closure;
Expand Down Expand Up @@ -2331,6 +2332,22 @@ public function dataUnion(): iterable
IntersectionType::class,
'array<int, string>&oversized-array',
];
yield [
[
new ObjectType(TestInterface::class),
new ClosureType([], new MixedType(), false),
],
UnionType::class,
'Bug9006\TestInterface|(Closure(): mixed)',
];
yield [
[
new ObjectType(TestInterface::class),
new ObjectType(Closure::class),
],
UnionType::class,
'Bug9006\TestInterface|Closure',
];
}

/**
Expand Down Expand Up @@ -3783,6 +3800,22 @@ public function dataIntersect(): iterable
IntersectionType::class,
'array<int, string>&oversized-array',
];
yield [
[
new ObjectType(TestInterface::class),
new ClosureType([], new MixedType(), false),
],
NeverType::class,
'*NEVER*=implicit',
];
yield [
[
new ObjectType(TestInterface::class),
new ObjectType(Closure::class),
],
NeverType::class,
'*NEVER*=implicit',
];
}

/**
Expand Down
8 changes: 8 additions & 0 deletions tests/PHPStan/Type/data/bug-9006.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Bug9006;

interface TestInterface
{

}

0 comments on commit 0dbe3ab

Please sign in to comment.