fixes #25046; Infinite loop with anonymous iterator (#25221)

fixes #25046

```nim
proc makeiter(v: string): iterator(): string =
  return iterator(): string =
    yield v

# loops
for c in makeiter("test")():
  echo "loops ", c
```
becomes

```nim
var temp = makeiter("test")
for c in temp():
  echo "loops ", c
```
for closures that might have side effects

(cherry picked from commit 31d64b57d5)
This commit is contained in:
ringabout
2025-10-15 18:11:15 +08:00
committed by narimiran
parent d01ea21451
commit cf5b89f573
2 changed files with 34 additions and 0 deletions

View File

@@ -975,6 +975,20 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; idgen: IdGenerator; owner: PSym):
for i in 0..<op.len-1:
result.add op[i]
elif op.kind != nkSym: # might have side effects
# bug #25046
# create a temp for the closure
# var :closureTemp
# :closureTemp = ...
let tempSym = newSym(skLet, getIdent(g.cache, ":closureTemp"), idgen, owner, body.info)
tempSym.typ = call[0].typ
let temp = newSymNode(tempSym)
var v = newNodeI(nkVarSection, body.info)
addVar(v, temp)
result.add(v)
result.add newAsgnStmt(temp, call[0], body.info)
call[0] = temp
var loopBody = newNodeI(nkStmtList, body.info, 3)
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
whileLoop[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))

View File

@@ -213,3 +213,23 @@ block:
discard call2()
pork()
# bug #25046
proc makeiter(v: string): iterator(): string =
return iterator(): string =
yield v
var flag = ""
var iter = makeiter("test1")
for c in iter():
flag = c
assert flag == "test1"
# loops
for c in makeiter("test2")():
flag = c
assert flag == "test2"