Repository navigation
Read untracked fetch links of an isset chain from the asking scope's state - #7065
Merged
Merged
Conversation
…state The chain links of an isset()/empty()/?? subject are walked under NonNullabilityHelper's ensured non-nullability, and ensuring a nested offset non-null also narrows the fetches it is read from. Their stored results therefore carry null-stripped types. IssetabilityDescriptor read an untracked receiver link through that stored result, so from three links on ($a['r']['a']['b'], $this->data['a']['b']) the verdict saw a nullable intermediate offset as non-null: isset() and ?? were typed as always set, the right side of ?? became unreachable and its merge dropped null from the subject, and the isset/?? rules reported the offset as always existing. An untracked array dim fetch, property fetch or static property fetch link is now read from the asking scope's state, derived from its receiver's state without a walk. Amp-Thread-ID: https://ampcode.com/threads/T-01a1d722-233f-76e4-a119-f3620177393b
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.
Fixes problem A of phpstan/phpstan#15722 (isset/
??narrowing leaking out of the expression for chains of three or more links).The chain links of an
isset()/empty()/??subject are walked underNonNullabilityHelper's ensured non-nullability. Ensuring a nested offset non-null also narrows the fetches it is read from, so the stored results of those links carry null-stripped types.IssetabilityDescriptorread an untracked receiver link through its stored result. From three links on ($p['r']['a']['b'],$this->data['a']['b']), the verdict therefore saw a nullable intermediate offset as non-null:isset($p['r']['a']['b'])wastrue, soisset(...) ? ... : nulllost itsnull(return.unusedType).$p['r']['a']['b'] ?? nullwasint. Its right side was unreachable, and merging the scopes dropped|nullfrom$pafter the expression (isset.offsetlater on).??rules reported the offset as always existing (nullCoalesce.offset,isset.offset), including for property-rooted chains, whose rule-facing re-pricing reused the stored results because$thisitself never changes.Two-link chains were not affected: there the receiver is the variable, which is always read from the scope.
An untracked array dim fetch, property fetch or static property fetch link is now read from the asking scope's state (
MutatingScope::getStateType()), derived from its receiver's state without a walk. Tracked links, nullsafe chains and other link kinds (calls) keep the previous reads. The native mirror inturbo-ext/src/IssetabilityDescriptor.cppgets the same change.Problem B of the issue (inverted correlation after
while) is the while loop's exit condition not re-applying its own assignments. That is the same root cause #7063 fixes inWhileHandler, so this PR leaves it out to avoid a conflict. With #7063,$stopisboolthere, which the issue accepts.Verified:
tests/PHPStan/Analyser/nsrt/bug-15722.phpand thetestBug15722cases inIssetRuleTest/NullCoalesceRuleTestfail without the change.make testspasses with and without the extension loaded.turbo-ext/tests/smoke.php,signature-parity.php, and method parity inside-by-side.php.