Fix #13217: Invalid second array value type in array_map#5099
Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Closed
Fix #13217: Invalid second array value type in array_map#5099phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
array_map#5099phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
…stant sizes - When array_map is called with multiple arrays of different known sizes, PHP pads shorter arrays with null, so callback parameters should be nullable - Fixed ParametersAcceptorSelector to add null to callback parameter types when constant array sizes provably differ - Fixed MutatingScope::getClosureType to apply the same logic for arrow functions and closure return type inference - Added regression test in tests/PHPStan/Analyser/nsrt/bug-13217.php Closes phpstan/phpstan#13217
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When
array_mapis called with multiple arrays of different lengths, PHP pads the shorter arrays withnullvalues. PHPStan was not accounting for this when determining callback parameter types, causing false positives like "Variable $bValue on left side of ?? always exists and is not nullable" when using the null coalescing operator on callback parameters that could actually be null.Changes
src/Reflection/ParametersAcceptorSelector.php: When building the refined callable type forarray_map's callback parameter, check if the array arguments have known constant sizes that differ. If so, addnullto each callback parameter type usingTypeCombinator::addNull().src/Analyser/MutatingScope.php: Apply the same null-padding logic ingetClosureType()when creatingDummyParameterobjects fromarrayMapArgsfor arrow functions and closure return type inference.tests/PHPStan/Analyser/nsrt/bug-13217.php: New regression test covering different-length arrays, same-length arrays, unknown-length arrays, arrow functions, same-variable arrays, and single-array cases.Root cause
PHPStan determines
array_mapcallback parameter types in two places:ParametersAcceptorSelector(lines 87-132): Creates a refined callable type likecallable(1|2, 3)based on the iterable value types of the array arguments. This determines the types used during the main closure body analysis.MutatingScope::getClosureType(lines 5707+): CreatesDummyParameterobjects fromarrayMapArgsfor computing closure/arrow function types.Both places extracted
getIterableValueType()from each array without considering that PHP'sarray_mappads shorter arrays withnull. The fix adds a check: when all arrays have a single known constant size and those sizes differ,nullis added to each callback parameter type.The fix is conservative — it only adds
nullwhen array sizes are provably different (known constant sizes). For arrays with unknown sizes, it does not addnullto avoid introducing false positives in generic code patterns likearray_map($callback, $this->items, array_keys($this->items)).Test
The regression test
tests/PHPStan/Analyser/nsrt/bug-13217.phpcovers:array_map(fn($a, $b) => ..., [1, 2], [3])— parameters are nullablearray_map(fn($a, $b) => ..., [1, 2], [3, 4])— parameters are NOT nullablearray_map(fn($a, $b) => ..., $a, $b)— parameters staymixed??: The original reproducing case —$bValue ?? 1no longer triggers false positivearray_map(fn($x, $y) => ..., $a, $a)— parameters staymixedFixes phpstan/phpstan#13217