Skip to content

Commit 739d87d

Browse files
committed
Use wider class-string when combining class strings with intersections
Fixes vimeo#10799
1 parent 87f7101 commit 739d87d

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

src/Psalm/Internal/Type/TypeCombiner.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,20 @@ private static function scrapeStringProperties(
10051005
if (!$type->as_type) {
10061006
$combination->class_string_types['object'] = new TObject();
10071007
} else {
1008-
$combination->class_string_types[$type->as] = $type->as_type;
1008+
if (isset($combination->class_string_types[$type->as])
1009+
&& $combination->class_string_types[$type->as] instanceof TNamedObject
1010+
) {
1011+
if ($combination->class_string_types[$type->as]->extra_types === []) {
1012+
// do nothing, existing type is wider or the same
1013+
} elseif ($type->as_type->extra_types === []) {
1014+
$combination->class_string_types[$type->as] = $type->as_type;
1015+
} else {
1016+
// todo: figure out what to do with class-string<A&B>|class-string<A&C>
1017+
$combination->class_string_types[$type->as] = $type->as_type;
1018+
}
1019+
} else {
1020+
$combination->class_string_types[$type->as] = $type->as_type;
1021+
}
10091022
}
10101023
} elseif ($type instanceof TLiteralString) {
10111024
if ($combination->strings !== null && count($combination->strings) < $literal_limit) {

tests/TypeCombinationTest.php

+7
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,13 @@ public function providerTestValidTypeCombination(): array
940940
'"0"',
941941
],
942942
],
943+
'unionOfClassStringAndClassStringWithIntersection' => [
944+
'class-string<IFoo>',
945+
[
946+
'class-string<IFoo>',
947+
'class-string<IFoo & IBar>',
948+
],
949+
],
943950
];
944951
}
945952

tests/TypeParseTest.php

+8
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,14 @@ public function testIntMaskOfWithValidValueOf(): void
11481148
$this->assertSame('int-mask-of<value-of<A::FOO>>', $docblock_type->getId());
11491149
}
11501150

1151+
public function testUnionOfClassStringAndClassStringWithIntersection(): void
1152+
{
1153+
$this->assertSame(
1154+
'class-string<IFoo>',
1155+
(string) Type::parseString('class-string<IFoo>|class-string<IFoo&IBar>'),
1156+
);
1157+
}
1158+
11511159
public function testReflectionTypeParse(): void
11521160
{
11531161
if (!function_exists('Psalm\Tests\someFunction')) {

0 commit comments

Comments
 (0)