Fix phpstan/phpstan#6799: wrongly reported empty array#5282
Closed
phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
Closed
Fix phpstan/phpstan#6799: wrongly reported empty array#5282phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
Conversation
… array arguments - Variables referenced via & in array literals passed as function arguments (e.g. call_user_func_array($cb, [&$var, ...])) are now invalidated after the function call, since the callee can modify them through the reference - Added invalidateByRefVariablesInArrayArg() to NodeScopeResolver::processArgs() - New regression test in tests/PHPStan/Analyser/nsrt/bug-6799.php
VincentLanglet
requested changes
Mar 23, 2026
Contributor
VincentLanglet
left a comment
There was a problem hiding this comment.
This will still produce errors on higher level since the variable is now mixed instead of array.
The main issue is the fact that
call_user_func_array(array($this, 'addFilter'), array(&$whereFilter, 'xxxx', $filters[$type], $value));
should be understood the same way than
$this->listingAddWhereFilterAtableDefault($whereFilter, 'xxxx', $filters[$type], $value);
…or by-ref variables Instead of blindly invalidating by-ref variables in array arguments to mixed, resolve the callback passed to call_user_func_array and use the callback's parameter types. This makes call_user_func_array([$this, 'method'], [&$var, ...]) equivalent to $this->method($var, ...) for type inference. - Add ArgumentsNormalizer::reorderCallUserFuncArrayArguments() to unpack array literal arguments into synthetic function call args - Add return type resolution for call_user_func_array in FuncCallHandler - Use callback parameter types for by-ref variables in processArgs - Fall back to mixed invalidation when callback cannot be resolved Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
|
That was the earlier test run — also already superseded by the clean full test run (11644 tests, all passing). Everything is good and already pushed. |
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 a variable is passed by reference inside an array literal that is used as a function argument (e.g.
call_user_func_array($callback, [&$var, ...])), PHPStan did not recognize that the variable could be modified by the function call. This caused false positives like "Comparison operation > between 0 and 0 is always false" when checking the count of an array that was passed by reference through an array argument.Changes
invalidateByRefVariablesInArrayArg()method tosrc/Analyser/NodeScopeResolver.phpthat recursively scans array literal arguments for by-reference items and invalidates those variablesprocessArgs()for all function call argumentstests/PHPStan/Analyser/nsrt/bug-6799.phpRoot cause
When
array(&$var, ...)is created inline as a function argument,processArrayByRefItems()(which sets up intertwined reference tracking) is never called because it only runs during array assignments to variables. The function call's argument processing also doesn't detect by-reference items inside array arguments — it only handles direct by-reference parameters. As a result,$var's type was never updated after the function call, keeping its original narrow type (e.g.array{}).The fix invalidates any variable that appears as a
&$varitem in an array literal passed as a function argument, setting it tomixedsince we cannot determine what the callee does with the reference.Test
Added
tests/PHPStan/Analyser/nsrt/bug-6799.phpwhich verifies that aftercall_user_func_array([$this, 'addFilter'], array(&$whereFilter, ...)), the type of$whereFilterismixed(notarray{}). Also tests a simpler case with a plain function call.Fixes phpstan/phpstan#6799