Fix phpstan/phpstan#11610: Optional array shape property doesn't change to required after is_array#5410
Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Closed
Conversation
… with null coalescing - When is_array($obj->prop ?? null) narrows a Coalesce expression to its left side PropertyFetch, also add HasPropertyType constraint on the object - This makes optional properties become required after type-checking through null coalescing - New regression test in tests/PHPStan/Analyser/nsrt/bug-11610.php Closes phpstan/phpstan#11610
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
When an object has an optional property (e.g.,
object{containers?: array<int>}) and the property is checked viais_array($obj->containers ?? null), the property should be narrowed from optional to required in the truthy branch. Previously, it stayed optional.Changes
src/Analyser/TypeSpecifier.phpin thecreateForExprmethod: when a Coalesce expression is simplified to its left-sidePropertyFetch(because the narrowed type excludes the right side), also emit aHasPropertyTypeconstraint on the object variable — mirroring whatisset()already does for property fetches.Root cause
In
createForExpr, whenis_array($obj->prop ?? null)is true, the Coalesce$obj->prop ?? nullis correctly simplified to$obj->prop(sincenullis not an array). The property expression itself was narrowed toarray<int>, but the object was not told that the property definitely exists. Theisset()handler already did this by addingHasPropertyTypeto the object, but the Coalesce simplification path increateForExprdid not.Test
Added
tests/PHPStan/Analyser/nsrt/bug-11610.phpwith two cases:is_array($obj->prop ?? null)— the bug case, now correctly narrows toobject{containers: array<int>}isset($obj->prop) || is_array($obj->prop)— already working, included for completenessFixes phpstan/phpstan#11610