Skip to content

Commit b033178

Browse files
committed
Fix the handling of sealed concrete classes
1 parent 05b80ef commit b033178

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

src/Reflection/Php/SealedAllowedSubTypesClassReflectionExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPStan\DependencyInjection\AutowiredService;
66
use PHPStan\Reflection\AllowedSubTypesClassReflectionExtension;
77
use PHPStan\Reflection\ClassReflection;
8+
use PHPStan\Type\ObjectType;
89
use PHPStan\Type\UnionType;
910
use function count;
1011

@@ -30,6 +31,10 @@ public function getAllowedSubTypes(ClassReflection $classReflection): array
3031
}
3132
}
3233

34+
if ($classReflection->isClass() && !$classReflection->isAbstract()) {
35+
$types[] = new ObjectType($classReflection->getName());
36+
}
37+
3338
return $types;
3439
}
3540

tests/PHPStan/Rules/Classes/AllowedSubTypesRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public function testSealed(): void
4444
]);
4545
}
4646

47+
public function testSealedOnConcreteClass(): void
48+
{
49+
$this->analyse([__DIR__ . '/data/sealed_concrete.php'], []);
50+
}
51+
4752
public static function getAdditionalConfigFiles(): array
4853
{
4954
return [
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SealedConcrete;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @phpstan-sealed a|b|c
9+
*/
10+
class s {}
11+
12+
final class a extends s {}
13+
final class b extends s {}
14+
final class c extends s {}
15+
16+
function foo(s $sealedClass): void
17+
{
18+
if ($sealedClass instanceof a) {
19+
return;
20+
}
21+
22+
assertType('SealedConcrete\\s~SealedConcrete\\a', $sealedClass);
23+
24+
if ($sealedClass instanceof b) {
25+
return;
26+
}
27+
28+
assertType('SealedConcrete\\s~(SealedConcrete\\a|SealedConcrete\\b)', $sealedClass);
29+
30+
if ($sealedClass instanceof c) {
31+
return;
32+
}
33+
34+
assertType('SealedConcrete\\s', $sealedClass);
35+
}

0 commit comments

Comments
 (0)