From ce4078acd40bb27de5d05832f486dbc95918a3c9 Mon Sep 17 00:00:00 2001 From: Tanguy Date: Thu, 30 Jun 2022 23:19:04 +0200 Subject: [PATCH] Allow recursive closure iterators (#19939) --- compiler/semexprs.nim | 3 ++- doc/manual.rst | 5 +---- tests/iter/titer_issues.nim | 13 +++++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ed28d81451..e07a984172 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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: diff --git a/doc/manual.rst b/doc/manual.rst index b63a2f68fb..571379a87b 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -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. diff --git a/tests/iter/titer_issues.nim b/tests/iter/titer_issues.nim index 15fe867c87..1f7e41e695 100644 --- a/tests/iter/titer_issues.nim +++ b/tests/iter/titer_issues.nim @@ -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