summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBung <crc32@qq.com>2022-10-21 15:59:05 +0800
committerGitHub <noreply@github.com>2022-10-21 09:59:05 +0200
commit66cbcaab8474f5ff3480e7a9bc55df249548a90c (patch)
treecb71c9901faaff9b7f8297cafa82104827a21bd3
parent84fab7f39bd89ef6e9c3e104a17af8d9f049d8e6 (diff)
downloadNim-66cbcaab8474f5ff3480e7a9bc55df249548a90c.tar.gz
fix #20152 Illegal capture of closure iterator, when should be legal (#20607)
-rw-r--r--compiler/lambdalifting.nim2
-rw-r--r--tests/closure/t20152.nim20
2 files changed, 21 insertions, 1 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index a34f4ba94..9790eefd8 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -458,7 +458,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
             else:
               discard addField(obj, s, c.graph.cache, c.idgen)
     # direct or indirect dependency:
-    elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s):
+    elif (innerProc and not s.isIterator and s.typ.callConv == ccClosure) or interestingVar(s):
       discard """
         proc outer() =
           var x: int
diff --git a/tests/closure/t20152.nim b/tests/closure/t20152.nim
new file mode 100644
index 000000000..484ea0741
--- /dev/null
+++ b/tests/closure/t20152.nim
@@ -0,0 +1,20 @@
+discard """

+  action: compile

+"""

+

+proc foo() =

+  iterator it():int {.closure.} =

+    yield 1

+  proc useIter() {.nimcall.} =

+    var iii = it # <-- illegal capture

+    doAssert iii() == 1

+  useIter()

+foo()

+

+proc foo2() =

+  proc bar() = # Local function, but not a closure, because no captures

+    echo "hi"

+  proc baz() {.nimcall.} = # Calls local function

+    bar()

+  baz()

+foo2()