Repository navigation
Conversation
When the scope branches of a check like `$r['o0'] ?? null` merge back, the shape and its narrowed variant are unioned. reduceArrays() merges them into the original shape, but optimizeConstantArrays() then counts the constant array values in the result (nested shapes included) and, above ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT, turns it into an oversized general array. A declared shape with more than 256 values in total therefore lost its keys after the first `??` on it. 2.2 did not reach optimizeConstantArrays() here: from the 63rd distinct key on, its key numbering overflowed and the arrays went through reduceArrays() without the optimization. 2.3 removed that numbering. The union is now kept as it is when it reduces to a single array that holds no more constant array values than the largest of the arrays it was made of - nothing grows, so there is nothing for the limit to bound. Closes phpstan/phpstan#15459
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.
For phpstan/phpstan#15459. Thanks @bmdevel for the report and the generator script.
When the branches of
$r['o0'] ?? nullmerge back, the declared shape and its narrowed variant (o0set and not null) are unioned.reduceArrays()merges them back into the declared shape, butprocessArrayTypes()then passes the result tooptimizeConstantArrays(). That function counts the constant array values in the result, nested shapes included. In the report this is 197 + 20 × 3 = 257, which is aboveConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT, so the shape is generalized tonon-empty-array<..., ...>&oversized-array. Every later read of a key on it then returns the union of all value types.2.2 never got to
optimizeConstantArrays()here. Its key numbering inprocessArrayTypes()overflowed at the 63rd distinct key, and the arrays then went throughreduceArrays($arrayTypes, false)and returned early. 2.3 removed that numbering, so large shapes now reach the limit check.With this change, a union that reduces to a single array is kept as it is when that array holds no more constant array values than the largest of the arrays it was made of. The limit is there to stop unions from growing, and a union like this one does not grow. Unions that do grow past the limit, and unions that stay as several arrays, are still optimized as before. The extra counting happens only when the single reduced array is above the limit. The same change is ported to
turbo-ext/src/TypeCombinator.cpp, with the regenerated declarations header and the version bump in a separate commit.tests/PHPStan/Analyser/nsrt/bug-15459.phpis the issue's reproducer, withdumpType()replaced byassertType(). Without the fix it fails with(array{currency: string, price: float}&oversized-array)|string|null. It passes with the fix, both with and without the Turbo extension loaded. The full test suite,smoke.php,signature-parity.phpandside-by-side.phppass.Closes phpstan/phpstan#15459