fixes #25240; forbids modifying a Deque changed while iterating over it (#25242)

fixes #25240

> Deque items behavior is not the same on 2.0.16 and 2.2.0

The behavior seems to be caused by the temp introduced for the parameter
`deq.len`, which prevents it from being evaluated multiple times

(cherry picked from commit b7c02e9bad)
This commit is contained in:
ringabout
2025-10-24 01:18:57 +08:00
committed by narimiran
parent 42f1c3944c
commit f1373637e7

View File

@@ -199,8 +199,10 @@ iterator items*[T](deq: Deque[T]): lent T =
let a = [10, 20, 30, 40, 50].toDeque
assert toSeq(a.items) == @[10, 20, 30, 40, 50]
for c in 0 ..< deq.len:
let L = len(deq)
for c in 0 ..< L:
yield deq.data[(deq.head + c.uint) and deq.mask]
assert(len(deq) == L, "the length of the Deque changed while iterating over it")
iterator mitems*[T](deq: var Deque[T]): var T =
## Yields every element of `deq`, which can be modified.
@@ -214,8 +216,10 @@ iterator mitems*[T](deq: var Deque[T]): var T =
x = 5 * x - 1
assert $a == "[49, 99, 149, 199, 249]"
for c in 0 ..< deq.len:
let L = len(deq)
for c in 0 ..< L:
yield deq.data[(deq.head + c.uint) and deq.mask]
assert(len(deq) == L, "the length of the Deque changed while iterating over it")
iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] =
## Yields every `(position, value)`-pair of `deq`.
@@ -225,8 +229,10 @@ iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] =
let a = [10, 20, 30].toDeque
assert toSeq(a.pairs) == @[(0, 10), (1, 20), (2, 30)]
for c in 0 ..< deq.len:
let L = len(deq)
for c in 0 ..< L:
yield (c, deq.data[(deq.head + c.uint) and deq.mask])
assert(len(deq) == L, "the length of the Deque changed while iterating over it")
proc contains*[T](deq: Deque[T], item: T): bool {.inline.} =
## Returns true if `item` is in `deq` or false if not found.