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
Open
Fix phpstan/phpstan#13688: Offset might not exist regression from phpstan 2.1.23#5361phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
- 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php: In thereportMaybesdecomposition 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.tests/PHPStan/Rules/Arrays/data/bug-13688.phptestBug13688intests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.phpRoot cause
The
NonexistentOffsetInArrayDimFetchCheckrule decomposes union types and checks each member individually for offset existence. For a union like''|':'with offset0, the empty string''correctly returns "no" forhasOffsetValueType(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.phpwhich reproduces the exact scenario from the issue: iterating over['', ':'], checkingstrlen > 0before accessing string offset. The test expects no errors.Fixes phpstan/phpstan#13688