diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index b5bb2be204..387587c5a6 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -121,7 +121,7 @@ public function accepts(Type $type, bool $strictTypes): TrinaryLogic public function isSuperTypeOf(Type $type): TrinaryLogic { - if ($type instanceof self) { + if ($type instanceof self || $type instanceof IntersectionType) { return $type->isSubTypeOf($this); } diff --git a/tests/PHPStan/Generics/GenericsIntegrationTest.php b/tests/PHPStan/Generics/GenericsIntegrationTest.php index 7ffb06e291..e88e973b8f 100644 --- a/tests/PHPStan/Generics/GenericsIntegrationTest.php +++ b/tests/PHPStan/Generics/GenericsIntegrationTest.php @@ -24,6 +24,7 @@ public function dataTopics(): array ['bug2620'], ['bug2622'], ['bug2627'], + ['bug6210'], ]; } diff --git a/tests/PHPStan/Generics/data/bug6210.php b/tests/PHPStan/Generics/data/bug6210.php new file mode 100644 index 0000000000..5a4202fd03 --- /dev/null +++ b/tests/PHPStan/Generics/data/bug6210.php @@ -0,0 +1,29 @@ +show($entity); + } + + /** + * @phpstan-param TEntityClass $entity + */ + private function show($entity): void + { + } +} diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 7e5ab97665..b31dc6c3e2 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -28,6 +28,7 @@ use PHPStan\Type\Generic\GenericClassStringType; use PHPStan\Type\Generic\GenericObjectType; use PHPStan\Type\Generic\TemplateBenevolentUnionType; +use PHPStan\Type\Generic\TemplateMixedType; use PHPStan\Type\Generic\TemplateObjectType; use PHPStan\Type\Generic\TemplateObjectWithoutClassType; use PHPStan\Type\Generic\TemplateType; @@ -1204,6 +1205,112 @@ public function dataUnion(): iterable UnionType::class, 'T of DateTime (function a(), parameter)|U of DateTime (function a(), parameter)', ], + 'bug6210-1' => [ + [ + new ObjectWithoutClassType(), + new IntersectionType([ + new ObjectWithoutClassType(), + new HasMethodType('getId'), + ]), + ], + ObjectWithoutClassType::class, + 'object', + ], + 'bug6210-2' => [ + [ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + null, + TemplateTypeVariance::createInvariant(), + ), + new IntersectionType([ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + null, + TemplateTypeVariance::createInvariant(), + ), + new HasMethodType('getId'), + ]), + ], + TemplateMixedType::class, + 'T (function a(), parameter)=explicit', + ], + 'bug6210-3' => [ + [ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + new ObjectWithoutClassType(), + TemplateTypeVariance::createInvariant(), + ), + new IntersectionType([ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + new ObjectWithoutClassType(), + TemplateTypeVariance::createInvariant(), + ), + new HasMethodType('getId'), + ]), + ], + TemplateObjectWithoutClassType::class, + 'T of object (function a(), parameter)', + ], + 'bug6210-4' => [ + [ + new ObjectWithoutClassType(), + new IntersectionType([ + new ObjectWithoutClassType(), + new HasPropertyType('getId'), + ]), + ], + ObjectWithoutClassType::class, + 'object', + ], + 'bug6210-5' => [ + [ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + null, + TemplateTypeVariance::createInvariant(), + ), + new IntersectionType([ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + null, + TemplateTypeVariance::createInvariant(), + ), + new HasPropertyType('getId'), + ]), + ], + TemplateMixedType::class, + 'T (function a(), parameter)=explicit', + ], + 'bug6210-6' => [ + [ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + new ObjectWithoutClassType(), + TemplateTypeVariance::createInvariant(), + ), + new IntersectionType([ + TemplateTypeFactory::create( + TemplateTypeScope::createWithFunction('a'), + 'T', + new ObjectWithoutClassType(), + TemplateTypeVariance::createInvariant(), + ), + new HasPropertyType('getId'), + ]), + ], + TemplateObjectWithoutClassType::class, + 'T of object (function a(), parameter)', + ], [ [ new BenevolentUnionType([new IntegerType(), new StringType()]),