Skip to content

Process reordered named arguments in call-site order in processArgs#5725

Open
phpstan-bot wants to merge 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-3ejzh2t
Open

Process reordered named arguments in call-site order in processArgs#5725
phpstan-bot wants to merge 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-3ejzh2t

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

When named arguments are passed in a different order than the parameter declaration, ArgumentsNormalizer reorders them to match declaration order for type checking. However, processArgs then processed arguments in this reordered order, so variable assignments in earlier call-site arguments were not visible in later ones. This caused false "Variable might not be defined" errors.

Changes

  • Modified NodeScopeResolver::processArgs() in src/Analyser/NodeScopeResolver.php to sort the argument processing order by the original argument's source position (using the ORIGINAL_ARG_ATTRIBUTE stored by ArgumentsNormalizer). Default-value fillers (without original args) are processed last since they have no side effects.
  • The parameter-matching index ($i) still refers to the reordered position, so parameter type checking, $closureBindScope handling, and by-reference detection remain correct.

Root cause

ArgumentsNormalizer::reorderArgs() reorders named arguments from call-site order to parameter-declaration order and stores the original Arg on each reordered arg via ORIGINAL_ARG_ATTRIBUTE. processArgs() then iterated over these reordered args sequentially, meaning scope mutations (variable assignments) happened in declaration order instead of evaluation order. When a later-declared parameter's argument referenced a variable assigned in an earlier call-site argument, the variable was not yet in scope.

All four call types (new, function call, method call, static method call) were affected equally because they all normalize arguments before passing them to processArgs.

Test

  • Added rule test tests/PHPStan/Rules/Variables/data/bug-9392.php covering the original reproducer (constructor with reordered named args) plus analogous cases for function calls, method calls, static method calls, and mixed positional/named arguments.
  • Added NSRT test tests/PHPStan/Analyser/nsrt/bug-9392.php to verify the inferred types of variables assigned in named arguments.

Fixes phpstan/phpstan#9392

- `ArgumentsNormalizer` reorders named arguments into parameter-declaration
  order for type checking. `processArgs` then processed them in this
  reordered order, causing variable assignments in earlier call-site
  arguments to be invisible to later ones.
- Sort the processing order in `processArgs` by the original argument's
  source position (via `ORIGINAL_ARG_ATTRIBUTE`) so scope mutations
  (variable assignments) happen in call-site evaluation order.
- Parameter matching still uses the reordered index, so type checking
  is unaffected.
- Affects all call types: `new`, function calls, method calls, and
  static method calls.
@ondrejmirtes
Copy link
Copy Markdown
Member

This needs more thought I think, the issue is really crazy and breaks a lot of assumptions.

@ondrejmirtes
Copy link
Copy Markdown
Member

Oh sorry, never mind, I thought this was about phpstan/phpstan#14661

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.

3 participants