Repository navigation
Do not attach the positional-arguments fix to the callback call synthesized from call_user_func() / call_user_func_array() - #6966
Open
phpstan-bot wants to merge 1 commit into
Conversation
…esized from `call_user_func()` / `call_user_func_array()` - CallUserFuncRule checks a FuncCall built by ArgumentsNormalizer. That node keeps the start/end positions of the original call_user_func(_array)() call, but its arguments are different: the callback argument is dropped, or the arguments come from the array items. - ReplacingNodeVisitor matches nodes by class and position, so the fix for a named argument under @no-named-arguments was applied to the real call_user_func(_array)() node. Its argument indexes did not match, which crashed with "clone(): Argument phpstan#1 ($object) must be of type object, null given" (or quietly rewrote call_user_func() into a broken call). - CallUserFuncRule now marks the synthesized call with FunctionCallParametersCheck::NOT_FIXABLE_CALL_ATTRIBUTE, and createPositionalArgumentsFix() does not create a fix for such calls, like it already does for attribute calls. The error is still reported. - Also checked the other FunctionCallParametersCheck::check() callers (CallToFunctionParametersRule, CallMethodsRule, CallStaticMethodsRule, InstantiationRule, CallCallablesRule): they pass real nodes from the file. AttributesCheck already opts out with `isAttribute`. The positional-arguments fix is the only fix this check attaches.
staabm
force-pushed
the
create-pull-request/patch-t43cm4k
branch
from
November 6, 2026 15:19
a10acaf to
fc3200a
Compare
clxmstaab
suggested changes
Nov 6, 2026
clxmstaab
left a comment
Contributor
There was a problem hiding this comment.
just testing the phpstan-bot
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
Analysing
\call_user_func_array([Foo::class, 'detect'], ['processTimeout' => 300])with a@no-named-argumentscallee crashed withInternal error: clone(): Argument #1 ($object) must be of type object, null given. The crash came from the fix that rewrites named arguments as positional ones. That fix was applied to the realcall_user_func_array()call instead of the callback call PHPStan builds internally. With this change, no fix is attached to that internal call. The error is still reported.Changes
src/Rules/FunctionCallParametersCheck.php: add theNOT_FIXABLE_CALL_ATTRIBUTEconstant.createPositionalArgumentsFix()returnsfalsefor calls that carry it, the same way it already does for calls built from attributes.src/Rules/Functions/CallUserFuncRule.php: set that attribute on the call built byArgumentsNormalizer::reorderCallUserFuncArguments()/reorderCallUserFuncArrayArguments().FunctionCallParametersCheck::check():CallToFunctionParametersRule,CallMethodsRule,CallStaticMethodsRule,InstantiationRuleandCallCallablesRulepass real nodes from the file, so they are fine.AttributesCheckalready opts out withisAttribute.Root cause
ArgumentsNormalizerbuilds the callback call with the attributes of the originalcall_user_func(_array)()node, including its file positions, so errors get the right line.ReplacingNodeVisitormatches the nodes to fix by class and position. So the fix closure was applied to the realcall_user_func(_array)()node, which has different arguments:call_user_func_array(), the argument indexes the fix expected did not exist, soclone nullcrashed.call_user_func(), the callback argument is shifted out, so the fix would quietly produce a wrong call.The argument lists of these internal calls do not match the source code, so they must not be fixed.
Test
CallUserFuncRuleTest::testBug15664runs the fixer ontests/PHPStan/Rules/Functions/data/bug-15664.php. The file contains the calls from the issue (call_user_func_arraywith named keys in different orders), pluscall_user_funcwith named arguments. The test asserts the file stays unchanged. Without the fix it crashes with__clone method called on non-object.Fixes phpstan/phpstan#15664