Skip to content

Fix phpstan/phpstan#4560: Unexpected array shape error#5173

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

Fix phpstan/phpstan#4560: Unexpected array shape error#5173
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-k0f79s5

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

When a mixed-typed variable (e.g. from $_POST) had array offsets explicitly set and was later narrowed to an array type via assertions like array_key_exists, the offset information from the explicit assignments was lost. This caused PHPStan to report false positives about array shapes.

Changes

  • Modified MutatingScope::addTypeToExpression() in src/Analyser/MutatingScope.php to incorporate existing array offset expression type holders when a variable's type is narrowed from mixed to an array type
  • Added regression test in tests/PHPStan/Analyser/nsrt/bug-4560.php

Root cause

When $data is mixed and $data['token'] = value is executed, MixedType::setOffsetValueType() returns mixed unchanged (by design, since mixed could be a string or other type). The offset information is tracked separately as an expression type holder for $data['token'].

Later, when assert(array_key_exists('password', $data)) narrows $data from mixed to array&hasOffset('password'), the narrowing did not check for existing expression type holders like $data['token']. So the hasOffset('token') information was lost from the final type.

The fix adds a post-narrowing step in addTypeToExpression(): when a variable transitions from MixedType to an array type, it scans existing expression type holders for ArrayDimFetch expressions with constant keys on the same variable, and enriches the narrowed type with HasOffsetValueType for each found offset.

Test

Added tests/PHPStan/Analyser/nsrt/bug-4560.php which reproduces the original issue: a mixed variable from $_POST with explicitly set ['token'] offset, then asserted via array_key_exists for 'password' and 'email' keys. The test verifies that the resulting type includes hasOffsetValue('token', mixed) alongside the hasOffset types from the assertions.

Fixes phpstan/phpstan#4560

- When a mixed-typed variable has array offsets set (e.g. $data['token'] = value)
  and is later narrowed to an array type (e.g. via array_key_exists assert),
  the existing offset information from expression type holders is now
  incorporated into the narrowed array type
- Added logic in MutatingScope::addTypeToExpression() to scan for existing
  ArrayDimFetch expression holders when a variable transitions from mixed to array
- New regression test in tests/PHPStan/Analyser/nsrt/bug-4560.php

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