File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -189,6 +189,7 @@ class NodeScopeResolver
189189 private const LOOP_SCOPE_ITERATIONS = 3 ;
190190 private const GENERALIZE_AFTER_ITERATION = 1 ;
191191 private const FOREACH_UNROLL_LIMIT = 16 ;
192+ private const FOREACH_UNROLL_NESTED_LIMIT = 16 ;
192193
193194 /** @var array<string, true> filePath(string) => bool(true) */
194195 private array $ analysedFiles = [];
@@ -3896,6 +3897,9 @@ private function tryProcessUnrolledConstantArrayForeach(
38963897 if ($ totalKeys === 0 || $ totalKeys > self ::FOREACH_UNROLL_LIMIT ) {
38973898 return null ;
38983899 }
3900+ if ($ context ->getForeachUnrollFactor () * $ totalKeys > self ::FOREACH_UNROLL_NESTED_LIMIT ) {
3901+ return null ;
3902+ }
38993903
39003904 $ nativeIterateeType = $ originalScope ->getNativeType ($ stmt ->expr );
39013905 $ nativeConstantArrays = $ nativeIterateeType ->getConstantArrays ();
@@ -3908,6 +3912,8 @@ private function tryProcessUnrolledConstantArrayForeach(
39083912 $ allChainScopes = [];
39093913 $ allBreakScopes = [];
39103914
3915+ $ bodyContext = $ context ->enterUnrolledForeach ($ totalKeys );
3916+
39113917 foreach ($ constantArrays as $ arrayIndex => $ constantArray ) {
39123918 $ keyTypes = $ constantArray ->getKeyTypes ();
39133919 $ valueTypes = $ constantArray ->getValueTypes ();
@@ -3971,7 +3977,7 @@ private function tryProcessUnrolledConstantArrayForeach(
39713977 $ iterScope ,
39723978 $ iterStorage ,
39733979 new NoopNodeCallback (),
3974- $ context ,
3980+ $ bodyContext ,
39753981 )->filterOutLoopExitPoints ();
39763982
39773983 $ iterEndScope = $ bodyResult ->getScope ();
Original file line number Diff line number Diff line change @@ -15,6 +15,7 @@ final class StatementContext
1515
1616 private function __construct (
1717 private bool $ isTopLevel ,
18+ private int $ foreachUnrollFactor = 1 ,
1819 )
1920 {
2021 }
@@ -40,13 +41,23 @@ public function isTopLevel(): bool
4041 return $ this ->isTopLevel ;
4142 }
4243
44+ public function getForeachUnrollFactor (): int
45+ {
46+ return $ this ->foreachUnrollFactor ;
47+ }
48+
4349 public function enterDeep (): self
4450 {
4551 if ($ this ->isTopLevel ) {
46- return self :: createDeep ( );
52+ return new self ( false , $ this -> foreachUnrollFactor );
4753 }
4854
4955 return $ this ;
5056 }
5157
58+ public function enterUnrolledForeach (int $ totalKeys ): self
59+ {
60+ return new self ($ this ->isTopLevel , $ this ->foreachUnrollFactor * $ totalKeys );
61+ }
62+
5263}
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ namespace Bug14590 ;
4+
5+ function provider (): array {
6+ $ cases = [];
7+ foreach ([1 , 2 ] as $ v0 ) {
8+ foreach ([1 , 2 ] as $ v1 ) {
9+ foreach ([1 , 2 ] as $ v2 ) {
10+ foreach ([1 , 2 ] as $ v3 ) {
11+ foreach ([1 , 2 ] as $ v4 ) {
12+ foreach ([1 , 2 ] as $ v5 ) {
13+ foreach ([1 , 2 ] as $ v6 ) {
14+ foreach ([1 , 2 ] as $ v7 ) {
15+ foreach ([1 , 2 ] as $ v8 ) {
16+ $ cases [] = $ v0 ;
17+ }
18+ }
19+ }
20+ }
21+ }
22+ }
23+ }
24+ }
25+ }
26+ return $ cases ;
27+ }
You can’t perform that action at this time.
0 commit comments