Skip to content

Commit 6597ef6

Browse files
committed
Fix reportNestedTooWideType (improve UnionType::traverseSimultaneously())
1 parent 8031040 commit 6597ef6

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed

src/Type/UnionType.php

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,28 +1143,35 @@ public function traverse(callable $cb): Type
11431143

11441144
public function traverseSimultaneously(Type $right, callable $cb): Type
11451145
{
1146-
$types = [];
1146+
$rightTypes = TypeUtils::flattenTypes($right);
1147+
$newTypes = [];
11471148
$changed = false;
1149+
foreach ($this->types as $innerType) {
1150+
$candidates = [];
1151+
foreach ($rightTypes as $i => $rightType) {
1152+
if (!$innerType->isSuperTypeOf($rightType)->yes()) {
1153+
continue;
1154+
}
11481155

1149-
if (!$right instanceof self) {
1150-
return $this;
1151-
}
1156+
$candidates[] = $rightType;
1157+
unset($rightTypes[$i]);
1158+
}
11521159

1153-
if (count($this->getTypes()) !== count($right->getTypes())) {
1154-
return $this;
1155-
}
1160+
if (count($candidates) === 0) {
1161+
$newTypes[] = $innerType;
1162+
continue;
1163+
}
11561164

1157-
foreach ($this->getSortedTypes() as $i => $leftType) {
1158-
$rightType = $right->getSortedTypes()[$i];
1159-
$newType = $cb($leftType, $rightType);
1160-
if ($leftType !== $newType) {
1165+
$newType = $cb($innerType, TypeCombinator::union(...$candidates));
1166+
if ($innerType !== $newType) {
11611167
$changed = true;
11621168
}
1163-
$types[] = $newType;
1169+
1170+
$newTypes[] = $newType;
11641171
}
11651172

11661173
if ($changed) {
1167-
return TypeCombinator::union(...$types);
1174+
return TypeCombinator::union(...$newTypes);
11681175
}
11691176

11701177
return $this;

tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ public function testNestedTooWideType(): void
295295
28,
296296
'Offset 0 (int) does not accept type int|null.',
297297
],
298+
[
299+
'Return type array<string, bool|int|string> of method NestedTooWideMethodReturnType\WebhookTest::dataTest() can be narrowed to array<string, int|string|true>.',
300+
115,
301+
],
298302
]);
299303
}
300304

tests/PHPStan/Rules/TooWideTypehints/data/nested-too-wide-method-return-type.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,20 @@ public function doFoo(): array
105105
}
106106

107107
}
108+
109+
final class WebhookTest
110+
{
111+
112+
/**
113+
* @return array<string, int|string|bool>
114+
*/
115+
public function dataTest(int $remoteId, string $hookUrl): array
116+
{
117+
return [
118+
'id' => $remoteId,
119+
'url' => $hookUrl,
120+
'push_events' => true,
121+
];
122+
}
123+
124+
}

0 commit comments

Comments
 (0)