Skip to content

Fix #8636: Oversimplified huge const array#4975

Closed
phpstan-bot wants to merge 2 commits into2.1.xfrom
create-pull-request/patch-lke8nmz
Closed

Fix #8636: Oversimplified huge const array#4975
phpstan-bot wants to merge 2 commits into2.1.xfrom
create-pull-request/patch-lke8nmz

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

When class constants or other array expressions contain more than 256 entries, PHPStan's OversizedArrayBuilder was using GeneralizePrecision::moreSpecific() to generalize individual key and value types. This produced overly complex types like literal-string&lowercase-string&non-falsy-string instead of simply string, making the oversized array types unnecessarily precise while still losing per-key shape information.

This fix changes the generalization to use GeneralizePrecision::lessSpecific(), producing cleaner and more practical types (e.g., non-empty-array<string, string>&oversized-array instead of non-empty-array<literal-string&lowercase-string&non-falsy-string, literal-string&lowercase-string&non-falsy-string>&oversized-array).

Changes

  • Changed GeneralizePrecision::moreSpecific() to GeneralizePrecision::lessSpecific() in src/Type/Constant/OversizedArrayBuilder.php (lines 84, 88)
  • Updated expected type descriptions in tests/PHPStan/Type/Constant/OversizedArrayBuilderTest.php for the 4 test cases that had literal-string&... patterns
  • Updated expected error message in tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php for the testBug8146bErrors test
  • Added regression test tests/PHPStan/Analyser/nsrt/bug-8636.php with two test classes covering string-keyed and int-keyed oversized arrays

Root cause

The OversizedArrayBuilder used GeneralizePrecision::moreSpecific() which converts constant string values like 'foo' into literal-string&lowercase-string&non-falsy-string (preserving accessory types). While this is more precise than string, it adds unnecessary complexity to oversized array types that have already lost their per-key shape information. Using lessSpecific() instead produces simple string and int types, which are more practical for downstream type checking and better match user expectations for generalized array types.

Test

Added tests/PHPStan/Analyser/nsrt/bug-8636.php with:

  • Config class with a 258-entry string-keyed constant array, testing that the oversized type is non-empty-array<string, string>&oversized-array and that key access returns string
  • MixedConfig class with a 258-entry int-keyed constant array mixing string and int values, testing that the oversized type is non-empty-list<int|string>&oversized-array

Fixes phpstan/phpstan#8636

phpstan-bot and others added 2 commits February 17, 2026 03:33
- Changed OversizedArrayBuilder to use GeneralizePrecision::lessSpecific()
  instead of moreSpecific() when generalizing key and value types
- This produces simpler types like `string` instead of
  `literal-string&lowercase-string&non-falsy-string` for oversized arrays
- New regression test in tests/PHPStan/Analyser/nsrt/bug-8636.php
- Updated expected types in OversizedArrayBuilderTest and ReturnTypeRuleTest
- The root cause was that moreSpecific generalization preserved accessory
  types that made oversized array types overly complex without adding value
Automated fix attempt 1 for CI failures.
@staabm staabm closed this Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants