Skip to content

Bail to MixedType in deep dim fetch writes on oversized arrays#5681

Open
phpstan-bot wants to merge 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-5sjqti6
Open

Bail to MixedType in deep dim fetch writes on oversized arrays#5681
phpstan-bot wants to merge 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-5sjqti6

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

  • Fix exponential slowdown when analysing deeply nested array structures with isset() checks in while loops
  • Bail to MixedType in produceArrayDimFetchAssignValueToWrite when dim fetch depth exceeds 5 and the type is already an oversized array (precision intentionally lost)
  • Reduces analysis time from 30+ seconds to ~5 seconds for the reproduction case

Detail

The root cause is in the DOWN walk of produceArrayDimFetchAssignValueToWrite. For code that builds deeply nested arrays (6+ levels of $out[$a][$b][$c][$d][$e][$f]), each level calls getOffsetValueType on the current type. After generalization marks the type as oversized (via OversizedArrayType in an intersection), continued drilling produces cascading intersectTypes and TypeCombinator::union operations that grow exponentially — without any precision gain, since oversized arrays already return MixedType from getOffsetValueType.

The fix recognizes this futility: when depth > 5 AND the current type is already oversized, substitute MixedType immediately instead of performing expensive type operations that will ultimately yield MixedType anyway.

Test plan

  • Regression bench test added: tests/bench/data/bug-14624.php
  • Full test suite passes (12077 tests, 79703 assertions)
  • make phpstan passes with no errors
  • Performance verified: 30s → 5s on reproduction case

Fixes phpstan/phpstan#14624

🤖 Generated with Claude Code

When produceArrayDimFetchAssignValueToWrite walks down through nested
ArrayDimFetch nodes, each level calls getOffsetValueType on the current
type. For deeply nested structures (6+ levels) where the type has already
been marked as an oversized array (precision intentionally lost), these
cascading operations produce exponential cost without useful precision
gain.

Stop drilling deeper when the dim fetch depth exceeds 5 AND the current
offsetValueType is already an oversized array, substituting MixedType
instead. This prevents expensive cascading intersectTypes/union operations
at levels where precision cannot be maintained anyway.

Closes phpstan/phpstan#14624
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