summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2022-11-29 13:41:38 +0800
committerGitHub <noreply@github.com>2022-11-29 06:41:38 +0100
commitd4afa53fd5fca70e4a09bb19bf34523b522ce309 (patch)
treee841916d374ea7e0e2ab76625a0118ce63271c66
parentb5a008bac8780098682b50874b81265e53569781 (diff)
downloadNim-d4afa53fd5fca70e4a09bb19bf34523b522ce309.tar.gz
fixes #13583; enforce void for `nkWhileStmt` (#20947)
* fixes #13583; enfore void for nkWhileStmt

* one more case
-rw-r--r--compiler/semstmts.nim5
-rw-r--r--tests/discard/tdiscardable.nim34
2 files changed, 39 insertions, 0 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 8d82007fb..f6b193f3d 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -38,6 +38,8 @@ const
   errPragmaOnlyInHeaderOfProcX = "pragmas are only allowed in the header of a proc; redefinition of $1"
   errCannotAssignToGlobal = "cannot assign local to global variable"
 
+proc implicitlyDiscardable(n: PNode): bool
+
 proc semDiscard(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1, c.config)
@@ -101,6 +103,9 @@ proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
     result.typ = c.enforceVoidContext
   elif efInTypeof in flags:
     result.typ = n[1].typ
+  elif implicitlyDiscardable(n[1]):
+    result[1].typ = c.enforceVoidContext
+    result.typ = c.enforceVoidContext
 
 proc semProc(c: PContext, n: PNode): PNode
 
diff --git a/tests/discard/tdiscardable.nim b/tests/discard/tdiscardable.nim
index 032050139..b13130a13 100644
--- a/tests/discard/tdiscardable.nim
+++ b/tests/discard/tdiscardable.nim
@@ -65,3 +65,37 @@ proc main2() =
 
 main1()
 main2()
+
+block: # bug #13583
+  block:
+    proc hello(): int {.discardable.} = 12
+
+    iterator test(): int {.closure.} =
+      while true:
+        hello()
+
+    let t = test
+
+  block:
+    proc hello(): int {.discardable.} = 12
+
+    iterator test(): int {.closure.} =
+      while true:
+        block:
+          yield 12
+          hello()
+
+    let t = test
+    doAssert t() == 12
+
+  block:
+    proc hello(): int {.discardable.} = 12
+
+    iterator test(): int {.closure.} =
+      while true:
+        yield 12
+        hello()
+
+    let t = test
+    doAssert t() == 12
+