Fix phpstan/phpstan#13669: Offset -1|0|1|2 might not exist on non-empty-array<-1|0|1|2, int>.#5030
Open
phpstan-bot wants to merge 2 commits into2.1.xfrom
Open
Fix phpstan/phpstan#13669: Offset -1|0|1|2 might not exist on non-empty-array<-1|0|1|2, int>.#5030phpstan-bot wants to merge 2 commits into2.1.xfrom
phpstan-bot wants to merge 2 commits into2.1.xfrom
Conversation
…t keys set in loop
When a constant array with all expected keys (e.g. array{-1: 0, 0: 0, 1: 0, 2: 0})
was modified inside a foreach loop via a union offset type covering all keys,
the intermediate expression type was derived top-down from the root property type,
producing a general array (array<-1|0|1|2, int>) that lost the constant structure.
During loop generalization, this general array couldn't confirm offset existence,
causing a false "Offset ... might not exist" error.
The fix computes improved intermediate types bottom-up using the scope's tracked
constant array types and setExistingOffsetValueType, preserving the constant array
structure through loop generalization.
Closes phpstan/phpstan#13669
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.
This PR fixes phpstan/phpstan#13669
Summary
Fixes a false positive where
++$this->mailCounts[$templateId][$mail]reported "Offset -1|0|1|2 might not exist on non-empty-array<-1|0|1|2, int>" even though all four keys were explicitly set in a constant array assignment immediately before the loop.Root Cause
In
NodeScopeResolver::produceArrayDimFetchAssignValueToWrite(), the additional expressions (intermediate array dim fetch types tracked in the scope) were computed by deriving top-down from the root property type. For a property typed asarray<int, array<MailStatus::CODE_*, int>>, derivinggetOffsetValueType()produces a generalarray<-1|0|1|2, int>— losing the constant array structure (array{-1: 0, 0: 0, 2: 0, 1: 0}) that the scope was actually tracking from the assignment.During loop generalization, the constant array (from before the loop body) was compared against this general array (from after), producing
non-empty-array<-1|0|1|2, int>. On this general array type,hasOffsetValueType(-1|0|1|2)returnsmaybe(neveryesforArrayType), triggering the false positive.Fix
Before building the additional expressions, the fix computes improved intermediate types bottom-up using the scope's tracked types. For each intermediate dim fetch where the scope holds a constant array type with all required offsets, it applies
setExistingOffsetValueType()with the child's offset type and value — preserving the constant array structure. This means loop generalization compares two constant arrays with matching keys, producing a constant array result wherehasOffsetValueType()correctly returnsyes.The forward/reverse passes that compute the root type are left unchanged, avoiding any risk of child expression invalidation during generalization.
Closes phpstan/phpstan#10349