Skip to content

Commit 3699e95

Browse files
ondrejmirtesclaude
andcommitted
Bail compact() enumeration for unsealed name arrays
`findConstantStrings` walked a constant array's explicit `getValueTypes()` to collect the variable names, so an unsealed names array — `compact(array{'foo', 'bar', ...<int, string>})` — produced a sealed `array{foo: ..., bar: ...}`, ignoring that the unsealed extras are further unknown variable names. Return `null` (give up the precise shape) when the names array is `isUnsealed()->yes()`, so the caller falls back to the general `array<string, mixed>` signature. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6988c81 commit 3699e95

2 files changed

Lines changed: 19 additions & 0 deletions

File tree

src/Type/Php/CompactFunctionReturnTypeExtension.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ private function findConstantStrings(Type $type): ?array
7575
}
7676

7777
if ($type instanceof ConstantArrayType) {
78+
// Unsealed extras are unknown further variable names that can't
79+
// be enumerated — bail so the caller falls back to the general
80+
// `compact()` signature.
81+
if ($type->isUnsealed()->yes()) {
82+
return null;
83+
}
84+
7885
$result = [];
7986
foreach ($type->getValueTypes() as $valueType) {
8087
$constantStrings = $this->findConstantStrings($valueType);

tests/PHPStan/Analyser/nsrt/compact.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,15 @@ function (string $dolor): void {
2020

2121
assertType('array{}', compact([]));
2222
};
23+
24+
/**
25+
* @param array{'foo', 'bar', ...<int, string>} $names
26+
*/
27+
function unsealedNames(array $names): void {
28+
$foo = 'x';
29+
$bar = 'y';
30+
// The unsealed `<int, string>` extras are unknown further variable
31+
// names, so the result can't be enumerated as a sealed shape — it
32+
// must widen to the general `compact()` signature.
33+
assertType('array<string, mixed>', compact($names));
34+
};

0 commit comments

Comments
 (0)