Skip to content

Commit 870a551

Browse files
committed
Return null from ArgumentsNormalizer::reorderArgs() when positional args after named args create holes beyond parameter count
- In `reorderArgs()`, positional arguments keep their original index from `$callArgs`. When a named argument appears between positional arguments (which is invalid PHP), the named arg is removed from the positional sequence, creating a hole in the `$reorderedArgs` array at an index beyond the parameter signature length. - The hole-filling loop at line 401 threw `ShouldNotHappenException` when encountering a hole index not present in `$signatureParameters`. - Replace the throw with `return null`, which tells all callers (func calls, method calls, static calls, `new`, `ParametersAcceptorSelector`) that argument reordering failed, and they fall back gracefully. - The fix applies to all callable types (functions, methods, static methods, constructors) since they all share `reorderArgs()`. - Added two test cases to `ArgumentsNormalizerTest::dataReorderInvalid`: one with a variadic parameter and one without.
1 parent ca00199 commit 870a551

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

src/Analyser/ArgumentsNormalizer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ public static function reorderArgs(ParametersAcceptor $parametersAcceptor, array
403403
continue;
404404
}
405405
if (!array_key_exists($j, $signatureParameters)) {
406-
throw new ShouldNotHappenException('Parameter signatures cannot have holes');
406+
return null;
407407
}
408408

409409
$parameter = $signatureParameters[$j];

tests/PHPStan/Analyser/ArgumentsNormalizerTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,33 @@ public static function dataReorderInvalid(): iterable
323323
[new StringType(), 'three'],
324324
],
325325
];
326+
327+
// positional arg after named arg with variadic parameter
328+
yield [
329+
[
330+
['value', false, false, null],
331+
['values', true, true, new StringType()],
332+
],
333+
[
334+
[new IntegerType(), null],
335+
[new IntegerType(), null],
336+
[new IntegerType(), null],
337+
[new StringType(), 'd'],
338+
[new IntegerType(), null],
339+
],
340+
];
341+
342+
// positional arg after named arg without variadic parameter
343+
yield [
344+
[
345+
['one', false, false, null],
346+
],
347+
[
348+
[new IntegerType(), null],
349+
[new StringType(), 'd'],
350+
[new IntegerType(), null],
351+
],
352+
];
326353
}
327354

328355
/**

0 commit comments

Comments
 (0)