Skip to content

Fix phpstan/phpstan#14265: Invalid "Offset might not exist on array"#5298

Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-zrgzbwy
Open

Fix phpstan/phpstan#14265: Invalid "Offset might not exist on array"#5298
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-zrgzbwy

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

When using array_keys($a) as input to a higher-order function like array_reduce, accessing $a[$key] inside the callback was incorrectly reported as "Offset might not exist" for arrays with optional keys. The keys returned by array_keys() are guaranteed to exist in the source array, so this was a false positive.

Changes

  • Added detectArrayKeysInSiblingArgs() method in src/Analyser/NodeScopeResolver.php that detects when array_keys($expr) appears as a sibling argument to a closure/arrow function in a function call
  • Added applyArrayKeysSourceToScope() method that injects type information for $expr[$param] into the callback scope, matching callback parameters whose type equals the source array's key type
  • Applied the detection in both the closure and arrow function processing paths within processArgs()
  • Applied the scope injection in both processArrowFunctionNode() and processClosureNode()
  • New regression test in tests/PHPStan/Rules/Arrays/data/bug-14265.php
  • New test method testBug14265() in NonexistentOffsetInArrayDimFetchRuleTest.php

Root cause

PHPStan already had special handling for foreach (array_keys($a) as $key) that assigned the type of $a[$key] in the loop scope, recognizing that keys from array_keys() are always valid offsets. However, this handling didn't extend to callbacks passed to higher-order functions like array_reduce(array_keys($a), fn($carry, $key) => $a[$key], ''). The type system lost the correlation between the array_keys() result and the source array, so $a[$key] was checked independently, producing a false "might not exist" warning for optional keys.

The fix extends the same approach: when a sibling argument in a function call is array_keys($expr), the callback scope is enriched with the knowledge that $expr[$param] has a valid type, preventing the false positive.

Test

Added a regression test reproducing the exact scenario from the issue: an array with an optional key (k2?), array_keys() passed to array_reduce, and the callback accessing the array with the key parameter. The test expects no errors.

Fixes phpstan/phpstan#14265

- When array_keys($a) is passed as argument alongside a closure/arrow function,
  PHPStan now recognizes that $a[$key] is valid inside the callback
- Extended the existing foreach(array_keys($a) as $key) special handling to
  also cover callbacks in function calls like array_reduce, array_map, etc.
- New regression test in tests/PHPStan/Rules/Arrays/data/bug-14265.php

Closes phpstan/phpstan#14265
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.

1 participant