Allow recursive closure iterators (#19939)

This commit is contained in:
Tanguy
2022-06-30 23:19:04 +02:00
committed by GitHub
parent 2c0aaac304
commit ce4078acd4
3 changed files with 16 additions and 5 deletions

View File

@@ -886,7 +886,8 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
case callee.kind
of skMacro, skTemplate: discard
else:
if callee.kind == skIterator and callee.id == c.p.owner.id:
if callee.kind == skIterator and callee.id == c.p.owner.id and
not isClosureIterator(c.p.owner.typ):
localError(c.config, n.info, errRecursiveDependencyIteratorX % callee.name.s)
# error correction, prevents endless for loop elimination in transf.
# See bug #2051:

View File

@@ -4326,13 +4326,10 @@ Closure iterators and inline iterators have some restrictions:
1. For now, a closure iterator cannot be executed at compile time.
2. `return` is allowed in a closure iterator but not in an inline iterator
(but rarely useful) and ends the iteration.
3. Neither inline nor closure iterators can be (directly)* recursive.
3. Inline iterators cannot be recursive.
4. Neither inline nor closure iterators have the special `result` variable.
5. Closure iterators are not supported by the JS backend.
(*) Closure iterators can be co-recursive with a factory proc which results
in similar syntax to a recursive iterator. More details follow.
Iterators that are neither marked `{.closure.}` nor `{.inline.}` explicitly
default to being inline, but this may change in future versions of the
implementation.

View File

@@ -29,6 +29,7 @@ end
9018
@[1, 2]
@[1, 2, 3]
1
'''
"""
@@ -274,3 +275,15 @@ iterator cc() {.closure.} =
break
var a2 = cc
# bug #16876
block:
iterator a(num: int): int {.closure.} =
if num == 1:
yield num
else:
for i in a(num - 1):
yield i
for i in a(5):
echo i