@@ -18,6 +18,8 @@ final class Accumulate implements \Iterator
18
18
private \Generator $ generator ;
19
19
/** @var list<S> */
20
20
private array $ values = [];
21
+ /** @var list<int<0, max>> */
22
+ private array $ cursors = [];
21
23
private bool $ started = false ;
22
24
23
25
/**
@@ -70,6 +72,11 @@ public function next(): void
70
72
71
73
public function rewind (): void
72
74
{
75
+ if (\is_int ($ cursor = \key ($ this ->values ))) {
76
+ /** @psalm-suppress InaccessibleProperty */
77
+ $ this ->cursors [] = $ cursor ;
78
+ }
79
+
73
80
/** @psalm-suppress InaccessibleProperty */
74
81
$ this ->started = true ;
75
82
/** @psalm-suppress InaccessibleProperty */
@@ -84,10 +91,20 @@ public function valid(): bool
84
91
$ valid = !$ this ->reachedCacheEnd () || $ this ->generator ->valid ();
85
92
86
93
if (!$ valid ) {
87
- // once the "true" end has been reached we automatically rewind this
88
- // iterator so it is always in a clean state
89
- /** @psalm-suppress UnusedMethodCall */
90
- $ this ->rewind ();
94
+ // once the "true" end has been reached we automatically rewind to
95
+ // the previous cursor position to allow correct iteration when
96
+ // nesting loops on the same iterator
97
+ /** @psalm-suppress InaccessibleProperty */
98
+ $ previousCursor = \array_pop ($ this ->cursors );
99
+ /** @psalm-suppress InaccessibleProperty */
100
+ \reset ($ this ->values );
101
+
102
+ if (\is_int ($ previousCursor )) {
103
+ while (\is_int (\key ($ this ->values )) && \key ($ this ->values ) !== $ previousCursor ) {
104
+ /** @psalm-suppress InaccessibleProperty */
105
+ \next ($ this ->values );
106
+ }
107
+ }
91
108
}
92
109
93
110
return $ valid ;
0 commit comments