Skip to content

Fix phpstan/phpstan#13688: Offset might not exist regression from phpstan 2.1.23#5361

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

Fix phpstan/phpstan#13688: Offset might not exist regression from phpstan 2.1.23#5361
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-x1usie4

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

False positive "Offset 0 might not exist on ''|':'" when accessing a string offset guarded by a strlen check through an intermediate variable ($inputLen = strlen($input); $inputLen > 0 && $input[$inputLen-1]).

Changes

  • Modified src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php: In the reportMaybes decomposition loop, skip reporting when the inner type is a string and the offset is an integer. This prevents the aggressive union decomposition from flagging valid string offset access patterns.
  • Added regression test tests/PHPStan/Rules/Arrays/data/bug-13688.php
  • Added test method testBug13688 in tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Root cause

The NonexistentOffsetInArrayDimFetchCheck rule decomposes union types and checks each member individually for offset existence. For a union like ''|':' with offset 0, the empty string '' correctly returns "no" for hasOffsetValueType(0), while ':' returns "yes". The union-level check returns "maybe", which is correct. However, the decomposition loop then flags the error because it finds one member that returns "no".

For strings, this decomposition is too aggressive because string offset validity is tied to string length. When the user has already guarded the access with a length check (e.g., $inputLen > 0), PHPStan narrows the length variable but can't propagate that narrowing back to the string type through the intermediate variable assignment. The fix skips the "might not exist" report for string types with integer offsets, relying on the union-level "maybe" check which is sufficient.

Test

Added tests/PHPStan/Rules/Arrays/data/bug-13688.php which reproduces the exact scenario from the issue: iterating over ['', ':'], checking strlen > 0 before accessing string offset. The test expects no errors.

Fixes phpstan/phpstan#13688

- Skip "might not exist" report for string types with integer offsets in
  NonexistentOffsetInArrayDimFetchCheck decomposition check
- When a union of constant strings (e.g. ''|':') is accessed with a valid
  integer offset, the decomposition incorrectly flagged it because one
  member (empty string) returned "no" for the offset
- The union-level check already correctly returns "maybe" for such cases
- New regression test in tests/PHPStan/Rules/Arrays/data/bug-13688.php

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