Skip to content

Fix phpstan/phpstan#6799: wrongly reported empty array#5282

Closed
phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-51z6kbf
Closed

Fix phpstan/phpstan#6799: wrongly reported empty array#5282
phpstan-bot wants to merge 2 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-51z6kbf

Conversation

@phpstan-bot
Copy link
Collaborator

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

  • Added invalidateByRefVariablesInArrayArg() method to src/Analyser/NodeScopeResolver.php that recursively scans array literal arguments for by-reference items and invalidates those variables
  • Called this method at the end of processArgs() for all function call arguments
  • Added regression test in tests/PHPStan/Analyser/nsrt/bug-6799.php

Root 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 &$var item in an array literal passed as a function argument, setting it to mixed since we cannot determine what the callee does with the reference.

Test

Added tests/PHPStan/Analyser/nsrt/bug-6799.php which verifies that after call_user_func_array([$this, 'addFilter'], array(&$whereFilter, ...)), the type of $whereFilter is mixed (not array{}). Also tests a simpler case with a plain function call.

Fixes phpstan/phpstan#6799

… 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
Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@phpstan-bot
Copy link
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.

@VincentLanglet VincentLanglet deleted the create-pull-request/patch-51z6kbf branch March 24, 2026 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants