Allow recursive closure iterators (#19939)

(cherry picked from commit ce4078acd4)
This commit is contained in:
Tanguy
2022-06-30 23:19:04 +02:00
committed by narimiran
parent d6ea7cc49a
commit ab1717984d
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

@@ -4339,13 +4339,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

@@ -41,6 +41,7 @@ In defer
trying
exception caught
finally block
1
'''
"""
@@ -380,3 +381,15 @@ iterator tryFinally() {.closure.} =
var x = tryFinally
x()
# 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