Skip to content

Fix phpstan/phpstan#13981: Assignment inside match statement no longer recognized#5120

Open
phpstan-bot wants to merge 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-hynebfv
Open

Fix phpstan/phpstan#13981: Assignment inside match statement no longer recognized#5120
phpstan-bot wants to merge 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-hynebfv

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

Assignment inside match arm conditions (e.g., is_dir($baseDir = dirname(__DIR__).'/lang') => $baseDir) stopped being recognized in PHPStan 2.1.34, causing false positive "Variable $baseDir might not be defined" errors. This fix restores correct variable scoping for match arm bodies.

Changes

  • Modified src/Analyser/NodeScopeResolver.php to transfer newly-defined variables from the condition processing scope to the arm body scope after filterByTruthyValue is applied
  • Added use function array_flip import for efficient variable lookup
  • Initialized $armCondResultScope before the condition loop to track the scope after condition processing
  • Added regression test tests/PHPStan/Rules/Variables/data/bug-13981.php
  • Added test method testBug13981 in tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php

Root cause

Commit 3beb8c626 ("Fix match analysis") changed how the match arm body scope is computed from $this->processExprNode($stmt, $filteringExpr, ...)->getTruthyScope() to $matchScope->filterByTruthyValue($filteringExpr). While processExprNode walks the AST and discovers variable assignments, filterByTruthyValue only performs type narrowing without AST traversal. This meant that any variable assignments occurring as side effects inside match arm conditions (like $baseDir = dirname(__DIR__).'/lang' inside is_dir(...)) were no longer carried into the arm body scope.

The fix detects variables that are newly defined in the condition processing scope (not present in $matchScope) and explicitly transfers them to the body scope.

Test

Added tests/PHPStan/Rules/Variables/data/bug-13981.php which reproduces the exact scenario from the issue: a match expression with is_dir($baseDir = dirname(__DIR__).'/lang') => $baseDir. The test expects no errors, confirming that the variable assignment in the condition is properly recognized in the arm body.

Fixes phpstan/phpstan#13981

staabm and others added 3 commits March 2, 2026 06:32
- Variable assignments in match arm conditions (e.g. `is_dir($baseDir = ...)`)
  were lost after commit 3beb8c6 replaced processExprNode with filterByTruthyValue
- filterByTruthyValue only narrows types without walking the AST, so assignments
  within condition expressions were not discovered for the arm body scope
- Fix transfers newly-defined variables from the condition processing scope to
  the body scope after applying truthiness filtering
- New regression test in tests/PHPStan/Rules/Variables/data/bug-13981.php

Closes phpstan/phpstan#13981
@VincentLanglet VincentLanglet self-assigned this Mar 3, 2026
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