summary refs log tree commit diff stats
path: root/tests/iter
diff options
context:
space:
mode:
Diffstat (limited to 'tests/iter')
-rw-r--r--tests/iter/t1550.nim24
-rw-r--r--tests/iter/t16076.nim45
-rw-r--r--tests/iter/t20891.nim28
-rw-r--r--tests/iter/t21306.nim118
-rw-r--r--tests/iter/t21737.nim22
-rw-r--r--tests/iter/t22148.nim15
-rw-r--r--tests/iter/t22548.nim21
-rw-r--r--tests/iter/t22619.nim83
-rw-r--r--tests/iter/t2771.nim25
-rw-r--r--tests/iter/tanoniter1.nim1
-rw-r--r--tests/iter/tarrayiter.nim14
-rw-r--r--tests/iter/tclosureiters.nim39
-rw-r--r--tests/iter/tgeniteratorinblock.nim54
-rw-r--r--tests/iter/titer.nim90
-rw-r--r--tests/iter/titer11.nim1
-rw-r--r--tests/iter/titer12.nim1
-rw-r--r--tests/iter/titer13.nim2
-rw-r--r--tests/iter/titer2.nim2
-rw-r--r--tests/iter/titer3.nim2
-rw-r--r--tests/iter/titer_issues.nim177
-rw-r--r--tests/iter/titervaropenarray.nim2
-rw-r--r--tests/iter/tmoditer.nim2
-rw-r--r--tests/iter/tpermutations.nim2
-rw-r--r--tests/iter/tshallowcopy_closures.nim1
-rw-r--r--tests/iter/tyieldintry.nim104
25 files changed, 832 insertions, 43 deletions
diff --git a/tests/iter/t1550.nim b/tests/iter/t1550.nim
new file mode 100644
index 000000000..c971943ee
--- /dev/null
+++ b/tests/iter/t1550.nim
@@ -0,0 +1,24 @@
+discard """
+  targets: "c js"
+"""
+
+type
+  A[T] = iterator(x: T): T {.gcsafe, closure.}
+
+iterator aimp[T](x: T): T {.gcsafe, closure.} =
+  var total = 0
+  while (total < 100):
+    yield total
+    total += x
+
+iterator bimp(y: A[int], z:int): int {.gcsafe, closure.} =
+  for i in y(z):
+    yield i
+
+for x in aimp[int](3):
+  discard x
+
+var y = aimp[int]
+var z = bimp
+for x in z(y, 1):
+  discard x
\ No newline at end of file
diff --git a/tests/iter/t16076.nim b/tests/iter/t16076.nim
new file mode 100644
index 000000000..2eb409068
--- /dev/null
+++ b/tests/iter/t16076.nim
@@ -0,0 +1,45 @@
+discard """
+  targets: "c js"
+"""
+
+proc main() =
+  block: # bug #17485
+    type
+      O = ref object
+        i: int
+
+    iterator t(o: O): int =
+      if o != nil:
+        yield o.i
+      yield 0
+
+    proc m =
+      var data = ""
+      for i in t(nil):
+        data.addInt i
+
+      doAssert data == "0"
+
+    m()
+
+
+  block: # bug #16076
+    type
+      R = ref object
+        z: int
+
+    var data = ""
+
+    iterator foo(x: int; y: R = nil): int {.inline.} =
+      if y == nil:
+        yield x
+      else:
+        yield y.z
+
+    for b in foo(10):
+      data.addInt b
+
+    doAssert data == "10"
+
+static: main()
+main()
diff --git a/tests/iter/t20891.nim b/tests/iter/t20891.nim
new file mode 100644
index 000000000..34deec41b
--- /dev/null
+++ b/tests/iter/t20891.nim
@@ -0,0 +1,28 @@
+import macros, tables
+
+var mapping {.compileTime.}: Table[string, NimNode]
+
+macro register(a: static[string], b: typed): untyped =
+  mapping[a] = b
+
+macro getPtr(a: static[string]): untyped =
+  result = mapping[a]
+
+proc foo() =
+  iterator it() {.closure.} =
+    discard
+  proc getIterPtr(): pointer {.nimcall.} =
+    rawProc(it)
+  register("foo", getIterPtr())
+  discard getIterPtr() # Comment either this to make it work
+foo() # or this
+
+proc bar() =
+  iterator it() {.closure.} =
+    discard getPtr("foo") # Or this
+    discard
+  proc getIterPtr(): pointer {.nimcall.} =
+    rawProc(it)
+  register("bar", getIterPtr())
+  discard getIterPtr()
+bar()
diff --git a/tests/iter/t21306.nim b/tests/iter/t21306.nim
new file mode 100644
index 000000000..4d0396294
--- /dev/null
+++ b/tests/iter/t21306.nim
@@ -0,0 +1,118 @@
+discard """
+  targets: "c js"
+"""
+
+# bug #21306
+type
+  FutureState {.pure.} = enum
+    Pending, Finished, Cancelled, Failed
+
+  FutureBase = ref object of RootObj
+    state: FutureState
+    error: ref CatchableError
+    id: uint
+
+  Future[T] = ref object of FutureBase
+    closure: iterator(f: Future[T]): FutureBase {.raises: [Defect, CatchableError, Exception], gcsafe.}
+    value: T
+
+template setupFutureBase() =
+  new(result)
+  result.state = FutureState.Pending
+
+proc newFutureImpl[T](): Future[T] =
+  setupFutureBase()
+
+template newFuture[T](fromProc: static[string] = ""): Future[T] =
+  newFutureImpl[T]()
+
+proc internalRead[T](fut: Future[T]): T =
+  when T isnot void:
+    return fut.value
+
+template await[T](f: Future[T]): untyped =
+  when declared(chronosInternalRetFuture):
+    when not declaredInScope(chronosInternalTmpFuture):
+      var chronosInternalTmpFuture {.inject.}: FutureBase = f
+    else:
+      chronosInternalTmpFuture = f
+
+    yield chronosInternalTmpFuture
+
+    when T isnot void:
+      cast[type(f)](chronosInternalTmpFuture).internalRead()
+
+type
+  VerifierError {.pure.} = enum
+    Invalid
+    MissingParent
+    UnviableFork
+    Duplicate
+  ProcessingCallback = proc() {.gcsafe, raises: [Defect].}
+  BlockVerifier =
+    proc(signedBlock: int):
+      Future[VerifierError] {.gcsafe, raises: [Defect].}
+
+  SyncQueueKind {.pure.} = enum
+    Forward, Backward
+
+  SyncRequest[T] = object
+    kind: SyncQueueKind
+    index: uint64
+    slot: uint64
+    count: uint64
+    item: T
+
+  SyncResult[T] = object
+    request: SyncRequest[T]
+    data: seq[ref int]
+
+  SyncQueue[T] = ref object
+    kind: SyncQueueKind
+    readyQueue: seq[SyncResult[T]]
+    blockVerifier: BlockVerifier
+
+iterator blocks[T](sq: SyncQueue[T],
+                    sr: SyncResult[T]): ref int =
+  case sq.kind
+  of SyncQueueKind.Forward:
+    for i in countup(0, len(sr.data) - 1):
+      yield sr.data[i]
+  of SyncQueueKind.Backward:
+    for i in countdown(len(sr.data) - 1, 0):
+      yield sr.data[i]
+
+proc push[T](sq: SyncQueue[T]; sr: SyncRequest[T]; data: seq[ref int];
+             processingCb: ProcessingCallback = nil): Future[void] {.
+    stackTrace: off, gcsafe.} =
+  iterator push_436208182(chronosInternalRetFuture: Future[void]): FutureBase {.
+      closure, gcsafe, raises: [Defect, CatchableError, Exception].} =
+    block:
+      template result(): auto {.used.} =
+        {.fatal: "You should not reference the `result` variable inside" &
+            " a void async proc".}
+
+      let item = default(SyncResult[T])
+      for blk in sq.blocks(item):
+        let res = await sq.blockVerifier(blk[])
+
+  var resultFuture = newFuture[void]("push")
+  resultFuture.closure = push_436208182
+  return resultFuture
+
+type
+  SomeTPeer = ref object
+    score: int
+
+proc getSlice(): seq[ref int] =
+  discard
+
+template smokeTest(kkind: SyncQueueKind, start, finish: uint64,
+                   chunkSize: uint64) =
+  var queue: SyncQueue[SomeTPeer]
+  var request: SyncRequest[SomeTPeer]
+  discard queue.push(request, getSlice())
+
+for k in {SyncQueueKind.Forward}:
+  for item in [(uint64(1181), uint64(1399), 41'u64)]:
+    smokeTest(k, item[0], item[1], item[2])
\ No newline at end of file
diff --git a/tests/iter/t21737.nim b/tests/iter/t21737.nim
new file mode 100644
index 000000000..da06faea7
--- /dev/null
+++ b/tests/iter/t21737.nim
@@ -0,0 +1,22 @@
+discard """
+  action: compile
+"""
+
+template mytoSeq*(iter: untyped): untyped =
+  var result: seq[typeof(iter)]# = @[]
+  for x in iter:
+    result.add(x)
+  result
+
+iterator test(dir:int): int =
+  yield 1234
+
+iterator walkGlobKinds (): int =
+  let dir2 = 123
+  let it = mytoSeq(test(dir2))  
+
+proc main()=
+    let it = iterator(): int=
+      for path in walkGlobKinds():
+          yield path
+main()
diff --git a/tests/iter/t22148.nim b/tests/iter/t22148.nim
new file mode 100644
index 000000000..9954eed87
--- /dev/null
+++ b/tests/iter/t22148.nim
@@ -0,0 +1,15 @@
+discard """

+  action: compile

+"""

+

+import std/memfiles

+

+# bug #22148

+proc make*(input: string) =

+  var inp = memfiles.open(input)

+  for line in memSlices(inp):

+    let lineF = MemFile(mem: line.data, size: line.size)

+    for word in memSlices(lineF, ','):

+      discard

+

+make("") # Must call to trigger

diff --git a/tests/iter/t22548.nim b/tests/iter/t22548.nim
new file mode 100644
index 000000000..b9abb75d0
--- /dev/null
+++ b/tests/iter/t22548.nim
@@ -0,0 +1,21 @@
+discard """
+  action: compile
+"""
+
+type Xxx[T] = object
+
+iterator x(v: string): char =
+  var v2: Xxx[int]
+
+  var y: v2.T
+
+  echo y
+
+proc bbb(vv: string): proc () =
+  proc xxx() =
+    for c in x(vv):
+      echo c
+
+  return xxx
+
+bbb("test")()
diff --git a/tests/iter/t22619.nim b/tests/iter/t22619.nim
new file mode 100644
index 000000000..6a98391f3
--- /dev/null
+++ b/tests/iter/t22619.nim
@@ -0,0 +1,83 @@
+# bug #22619
+
+when false: # todo fixme
+  block:
+    type
+      Resource = object
+        value: int
+  
+      Object = object
+        r {.cursor.}: Resource
+        s {.cursor.}: seq[Resource]
+  
+    var numDestroy = 0
+  
+    proc `=copy`(x: var Resource, y: Resource) {.error.} # disallow full copies
+    proc `=destroy`(x: Resource) =
+      inc numDestroy
+  
+    proc test() =
+      # perform the test in procedure so that globals aren't used (their different
+      # semantics with regards to destruction would interfere)
+      var
+        r = Resource(value: 1) # initialize a resource
+        s = @[Resource(value: 2)]
+  
+      # make sure no copy is required in the initializer expression:
+      var o = Object(r: r, s: s)
+  
+      # copying the object doesn't perform a full copy of the cursor fields:
+      var o2 = o
+      discard addr(o2) # prevent `o2` from being turned into a cursor
+  
+      # check that the fields were shallow-copied:
+      doAssert o2.r.value == 1
+      doAssert o2.s[0].value == 2
+  
+      # make sure no copy is required with normal field assignments:
+      o.r = r
+      o.s = s
+  
+  
+      # when `o` and `o2` are destroyed, their destructor must not be called on
+      # their fields
+  
+    test()
+  
+    # one call for the `r` local and one for the object in `s`
+    doAssert numDestroy == 2
+
+block:
+  type Value = distinct int
+
+  var numDestroy = 0
+
+  when defined(gcRefc):
+    proc `=destroy`(x: var Value) =
+      inc numDestroy
+  else:
+    proc `=destroy`(x: Value) =
+      inc numDestroy
+
+  iterator iter(s: seq[Value]): int {.closure.} =
+    # because it is used across yields, `s2` is lifted into the iterator's
+    # environment. Since non-ref cursors in object didn't have their hooks
+    # disabled inside the environments lifted hooks, this led to double
+    # frees
+    var s2 {.cursor.} = s
+    var i = 0
+    let L = s2.len
+    while i < L:
+      yield s2[i].int
+      inc i
+
+  proc test() =
+    var s = @[Value(1), Value(2)]
+    let cl = iter
+    # make sure resuming the iterator works:
+    doAssert cl(s) == 1
+    doAssert cl(s) == 2
+    doAssert cl(s) == 0
+
+  test()
+  doAssert numDestroy == 2
diff --git a/tests/iter/t2771.nim b/tests/iter/t2771.nim
new file mode 100644
index 000000000..71a8a9dcd
--- /dev/null
+++ b/tests/iter/t2771.nim
@@ -0,0 +1,25 @@
+discard """
+  targets: "c js"
+"""
+
+template t1(i: int): int=
+  i+1
+template t2(i: int): int=
+  i+1
+
+doAssert t1(10).t2() == 12
+
+
+template it1(i: int): iterator(): int =
+  iterator result(): int {.closure, gensym.} =
+    yield i+1
+  result
+
+template it2(iter: iterator(): int): iterator(): int =
+  iterator result(): int {.closure, gensym.} =
+    yield iter()+1
+  result
+
+let x2 = it1(10).it2()
+
+doAssert x2() == 12
diff --git a/tests/iter/tanoniter1.nim b/tests/iter/tanoniter1.nim
index 9f0d0a74b..fee16497f 100644
--- a/tests/iter/tanoniter1.nim
+++ b/tests/iter/tanoniter1.nim
@@ -1,4 +1,5 @@
 discard """
+  targets: "c js"
   output: '''1
 2
 3
diff --git a/tests/iter/tarrayiter.nim b/tests/iter/tarrayiter.nim
new file mode 100644
index 000000000..eb7ba591a
--- /dev/null
+++ b/tests/iter/tarrayiter.nim
@@ -0,0 +1,14 @@
+block:
+  iterator `[]`(a: int, r: int): int = 
+    for q in 0 .. r:
+      yield a
+    
+  for val in 10[2]: discard
+  
+  type Custom = distinct string
+
+  iterator `[]`(a: Custom, r: int): char = 
+    for q in 0 .. r:
+      yield a.string[q]
+      
+  for val in Custom("test")[2]: discard
\ No newline at end of file
diff --git a/tests/iter/tclosureiters.nim b/tests/iter/tclosureiters.nim
index 345a4867a..4a2639852 100644
--- a/tests/iter/tclosureiters.nim
+++ b/tests/iter/tclosureiters.nim
@@ -1,4 +1,5 @@
 discard """
+  targets: "c js"
   output: '''0
 1
 2
@@ -19,7 +20,18 @@ discard """
 0
 1
 2
-70'''
+70
+0
+(1, 1)
+(1, 2)
+(1, 3)
+(2, 1)
+(2, 2)
+(2, 3)
+(3, 1)
+(3, 2)
+(3, 3)
+'''
 """
 
 when true:
@@ -96,7 +108,7 @@ proc unused =
 iterator lineIter2*(filename: string): string {.closure.} =
   var f = open(filename, bufSize=8000)
   defer: close(f)   # <-- commenting defer "solves" the problem
-  var res = TaintedString(newStringOfCap(80))
+  var res = newStringOfCap(80)
   while f.readLine(res): yield res
 
 proc unusedB =
@@ -139,3 +151,26 @@ iterator filesIt(path: string): auto {.closure.} =
     let prefix = path.splitPath[1]
     for f in files:
       yield prefix / f
+
+# bug #13815
+when not defined(js):
+  var love = iterator: int {.closure.} =
+    yield cast[type(
+      block:
+        var a = 0
+        yield a
+        a)](0)
+
+  for i in love():
+    echo i
+else:
+  echo 0
+
+# bug #18474
+iterator pairs(): (int, int) {.closure.} =
+  for i in 1..3:
+    for j in 1..3:
+      yield (i, j)
+
+for pair in pairs():
+  echo pair
diff --git a/tests/iter/tgeniteratorinblock.nim b/tests/iter/tgeniteratorinblock.nim
new file mode 100644
index 000000000..2ab903996
--- /dev/null
+++ b/tests/iter/tgeniteratorinblock.nim
@@ -0,0 +1,54 @@
+discard """
+  output: '''30
+60
+90
+150
+180
+210
+240
+60
+180
+240
+[60, 180, 240]
+[60, 180]'''
+"""
+import std/enumerate
+
+template map[T; Y](i: iterable[T], fn: proc(x: T): Y): untyped =
+  iterator internal(): Y  {.gensym.} =
+    for it in i:
+      yield fn(it)
+  internal()
+
+template filter[T](i: iterable[T], fn: proc(x: T): bool): untyped =
+  iterator internal(): T {.gensym.} =
+    for it in i:
+      if fn(it):
+        yield it
+  internal()
+
+template group[T](i: iterable[T], amount: static int): untyped =
+  iterator internal(): array[amount, T] {.gensym.} =
+    var val: array[amount, T]
+    for ind, it in enumerate i:
+      val[ind mod amount] = it
+      if ind mod amount == amount - 1:
+        yield val
+  internal()
+
+var a = [10, 20, 30, 50, 60, 70, 80]
+
+proc mapFn(x: int): int = x * 3
+proc filterFn(x: int): bool = x mod 20 == 0
+
+for x in a.items.map(mapFn):
+  echo x
+
+for y in a.items.map(mapFn).filter(filterFn):
+  echo y
+
+for y in a.items.map(mapFn).filter(filterFn).group(3):
+  echo y
+
+for y in a.items.map(mapFn).filter(filterFn).group(2):
+  echo y
diff --git a/tests/iter/titer.nim b/tests/iter/titer.nim
index 22be1bad5..b03d43f36 100644
--- a/tests/iter/titer.nim
+++ b/tests/iter/titer.nim
@@ -55,3 +55,93 @@ const
 for i in 0..len(stringArray)-1:
   echo(stringArray[i])
 
+# bug #15360
+
+type Rule[T] = (int, T)
+
+var t: seq[Rule[int]]
+for (c, t) in t:
+  discard
+
+
+
+import std/sugar
+
+# bug #14165
+iterator log_nodups_hamming(): int {.inline.} =
+  let lb3 = 1
+  let lb4 = 123
+  proc mul3(): int = lb3 + lb4
+  yield mul3()
+
+for h in log_nodups_hamming():
+  break
+for h in log_nodups_hamming():
+  break
+for h in log_nodups_hamming():
+  break
+
+# bug #18536
+iterator envPairs*(): int =
+  var foo: seq[int]
+  proc fun() =
+    foo = @[]
+  fun()
+  yield 3
+
+proc main() =
+  for a in envPairs():
+    discard
+  for a in envPairs():
+    discard
+static: main()
+main()
+
+# bug #6269
+iterator makeFn(outer_val: int): proc(a: int): int =
+  for i in 0..1:
+    yield proc(a:int): int =
+      return a + i.int
+
+let v1 = 42
+
+let res = collect:
+  for fn1 in makeFn(v1):
+    let v2 = fn1(v1)
+    for fn2 in makeFn(v2):
+      fn2(v2)
+
+doAssert res == @[42, 43, 43, 44]
+
+block: # bug #21110
+  iterator p(): int =
+    when nimvm:
+      yield 0
+    else:
+      yield 0
+
+  template foo =
+    for k in p():
+      let m = ""
+      proc e() = discard m & ""
+      e()
+  static: foo()
+  foo()
+
+
+# bug #15924
+iterator walk(): (int, int) {.closure.} =
+  yield (10,11)
+
+for (i,j) in walk():
+  doAssert i == 10
+
+proc main123() =
+  let x = false
+  iterator it(): (bool, bool) {.closure.} = # normally {.closure.} here makes #21476 work
+    discard x
+
+  for (_, _) in it():
+    discard
+
+main123()
diff --git a/tests/iter/titer11.nim b/tests/iter/titer11.nim
index 2b39c74f7..153b3c29a 100644
--- a/tests/iter/titer11.nim
+++ b/tests/iter/titer11.nim
@@ -1,4 +1,5 @@
 discard """
+targets: "c js"
 output: '''
 [
 1
diff --git a/tests/iter/titer12.nim b/tests/iter/titer12.nim
index f7fc64da4..f264a0e82 100644
--- a/tests/iter/titer12.nim
+++ b/tests/iter/titer12.nim
@@ -1,4 +1,5 @@
 discard """
+targets: "c js"
 output: '''
 Selecting 2
 1.0
diff --git a/tests/iter/titer13.nim b/tests/iter/titer13.nim
index 0d4a399c5..086c40ca4 100644
--- a/tests/iter/titer13.nim
+++ b/tests/iter/titer13.nim
@@ -72,7 +72,7 @@ block:
     echo a
 
 block t5859:
-  proc flatIterator[T](s: openarray[T]): auto {.noSideEffect.}=
+  proc flatIterator[T](s: openArray[T]): auto {.noSideEffect.}=
     result = iterator(): auto =
       when (T is not seq|array):
         for item in s:
diff --git a/tests/iter/titer2.nim b/tests/iter/titer2.nim
index f60aed73a..975cc786c 100644
--- a/tests/iter/titer2.nim
+++ b/tests/iter/titer2.nim
@@ -17,7 +17,7 @@ type
   TSlotEnum = enum seEmpty, seFilled, seDeleted
   TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
   TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
-  TTable* {.final.}[A, B] = object
+  TTable*[A, B] {.final.} = object
     data: TKeyValuePairSeq[A, B]
     counter: int
 
diff --git a/tests/iter/titer3.nim b/tests/iter/titer3.nim
index 9dcfd7be5..defd56c98 100644
--- a/tests/iter/titer3.nim
+++ b/tests/iter/titer3.nim
@@ -26,7 +26,7 @@ var x = [[1, 2, 3], [4, 5, 6]]
 for y in iter1(x[0]): write(stdout, $y)
 writeLine(stdout, "")
 
-# ensure closure and inline iterators have the same behaviour wrt
+# ensure closure and inline iterators have the same behaviour regarding
 # parameter passing
 
 iterator clo(a: int): int {.closure.} =
diff --git a/tests/iter/titer_issues.nim b/tests/iter/titer_issues.nim
index 872ebe2b7..c82b3902d 100644
--- a/tests/iter/titer_issues.nim
+++ b/tests/iter/titer_issues.nim
@@ -1,4 +1,5 @@
 discard """
+  target: "c js"
   output: '''
 0
 1
@@ -27,6 +28,21 @@ end
 9014
 9016
 9018
+@[1, 2]
+@[1, 2, 3]
+1
+nested finally
+outer finally
+nested finally
+outer finally
+nested finally
+outer finally
+nested finally
+outer finally
+In defer
+trying
+exception caught
+finally block
 '''
 """
 
@@ -133,7 +149,7 @@ block t3837_chained:
 
 
 block t3221_complex:
-  iterator permutations[T](ys: openarray[T]): seq[T] =
+  iterator permutations[T](ys: openArray[T]): seq[T] =
     var
       d = 1
       c = newSeq[int](ys.len)
@@ -191,7 +207,7 @@ block t3499_keepstate:
       break
 
   # bug #3499 last snippet fixed
-  # bug 705  last snippet fixed
+  # bug #705  last snippet fixed
 
 
 
@@ -225,8 +241,8 @@ block t2023_objiter:
 
 
 block:
-  # issue #13739
-  iterator myIter(arg: openarray[int]): int =
+  # bug #13739
+  iterator myIter(arg: openArray[int]): int =
     var tmp = 0
     let len = arg.len
     while tmp < len:
@@ -240,3 +256,156 @@ block:
       echo x
 
   someProc()
+
+block:
+  # bug #12576
+  iterator ff(sq: varargs[seq[int]]): int =
+    for x in sq:
+      echo x
+
+  for x in ff(@[1, 2], @[1, 2, 3]):
+    echo x
+
+
+# bug #19575
+
+iterator bb() {.closure.} =
+    while true:
+        try: discard
+        except: break
+        finally: break
+
+var a = bb
+
+iterator cc() {.closure.} =
+    while true:
+        try: discard
+        except:
+          if true:
+            break
+        finally:
+          if true:
+            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
+
+block:
+  # bug #19911 (return in nested try)
+
+  # try yield -> try
+  iterator p1: int {.closure.} =
+    try:
+      yield 0
+      try:
+        return
+      finally:
+        echo "nested finally"
+      echo "shouldn't run"
+    finally:
+      echo "outer finally"
+    echo "shouldn't run"
+
+  for _ in p1():
+    discard
+
+  # try -> try yield
+  iterator p2: int {.closure.} =
+    try:
+      try:
+        yield 0
+        return
+      finally:
+        echo "nested finally"
+      echo "shouldn't run"
+    finally:
+      echo "outer finally"
+    echo "shouldn't run"
+
+  for _ in p2():
+    discard
+
+  # try yield -> try yield
+  iterator p3: int {.closure.} =
+    try:
+      yield 0
+      try:
+        yield 0
+        return
+      finally:
+        echo "nested finally"
+      echo "shouldn't run"
+    finally:
+      echo "outer finally"
+    echo "shouldn't run"
+
+  for _ in p3():
+    discard
+
+  # try -> try
+  iterator p4: int {.closure.} =
+    try:
+      try:
+        return
+      finally:
+        echo "nested finally"
+      echo "shouldn't run"
+    finally:
+      echo "outer finally"
+    echo "shouldn't run"
+
+  for _ in p4():
+    discard
+
+# bug #18824
+iterator poc_iterator: int {.closure.}  =
+  block bug18824:
+    try:
+      break bug18824
+    finally:
+      echo "In defer"
+
+for _ in poc_iterator():
+  discard
+
+# bug #20624
+iterator tryFinally() {.closure.} =
+  block route:
+    try:
+      echo "trying"
+      raise
+    except:
+      echo "exception caught"
+      break route
+    finally:
+      echo "finally block"
+
+var x = tryFinally
+x()
+
+block: # bug #24033
+  type Query = ref object
+
+  iterator pairs(query: Query): (int, (string, float32)) =
+    var output: (int, (string, float32)) = (0, ("foo", 3.14))
+    for id in @[0, 1, 2]:
+      output[0] = id
+      yield output
+
+  var collections: seq[(int, string, string)]
+
+  for id, (str, num) in Query():
+    collections.add (id, str, $num)
+
+  doAssert collections[1] == (1, "foo", "3.14")
diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim
index 4469fdcf5..b2fe71ceb 100644
--- a/tests/iter/titervaropenarray.nim
+++ b/tests/iter/titervaropenarray.nim
@@ -1,6 +1,6 @@
 discard """
   output: "123"
-  targets: "C"
+  targets: "c cpp"
 """
 # Try to break the transformation pass:
 iterator iterAndZero(a: var openArray[int]): int =
diff --git a/tests/iter/tmoditer.nim b/tests/iter/tmoditer.nim
index b92a416fb..99e5b642d 100644
--- a/tests/iter/tmoditer.nim
+++ b/tests/iter/tmoditer.nim
@@ -43,7 +43,7 @@ proc `=copy`(dst: var NonCopyable, src: NonCopyable) {.error.}
 proc `=sink`(dst: var NonCopyable, src: NonCopyable) =
   dst.x = src.x
 
-iterator lentItems[T](a: openarray[T]): lent T =
+iterator lentItems[T](a: openArray[T]): lent T =
   for i in 0..a.high:
     yield a[i]
 
diff --git a/tests/iter/tpermutations.nim b/tests/iter/tpermutations.nim
index c5067ba31..30a66460f 100644
--- a/tests/iter/tpermutations.nim
+++ b/tests/iter/tpermutations.nim
@@ -12,7 +12,7 @@ perm: 6778800.0 det: 0.0
 
 import sequtils, sugar
 
-iterator permutations*[T](ys: openarray[T]): tuple[perm: seq[T], sign: int] =
+iterator permutations*[T](ys: openArray[T]): tuple[perm: seq[T], sign: int] =
   var
     d = 1
     c = newSeq[int](ys.len)
diff --git a/tests/iter/tshallowcopy_closures.nim b/tests/iter/tshallowcopy_closures.nim
index 279e7d950..06b04a788 100644
--- a/tests/iter/tshallowcopy_closures.nim
+++ b/tests/iter/tshallowcopy_closures.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc"
   ccodecheck: "!@('{' \\s* 'NI HEX3Astate;' \\s* '}')"
   output: '''
 a1 10
diff --git a/tests/iter/tyieldintry.nim b/tests/iter/tyieldintry.nim
index 35df55c24..e51ab7f0d 100644
--- a/tests/iter/tyieldintry.nim
+++ b/tests/iter/tyieldintry.nim
@@ -1,17 +1,16 @@
 discard """
-targets: "c"
-output: "ok"
+  matrix: "; --experimental:strictdefs; -d:nimOptIters"
+  targets: "c cpp"
 """
-var closureIterResult = newSeq[int]()
 
-# XXX Investigate why this fails now for 'nim cpp'
+var closureIterResult = newSeq[int]()
 
 proc checkpoint(arg: int) =
   closureIterResult.add(arg)
 
 type
-  TestException = object of Exception
-  AnotherException = object of Exception
+  TestError = object of CatchableError
+  AnotherError = object of CatchableError
 
 proc testClosureIterAux(it: iterator(): int, exceptionExpected: bool, expectedResults: varargs[int]) =
   closureIterResult.setLen(0)
@@ -21,7 +20,7 @@ proc testClosureIterAux(it: iterator(): int, exceptionExpected: bool, expectedRe
   try:
     for i in it():
       closureIterResult.add(i)
-  except TestException:
+  except TestError:
     exceptionCaught = true
 
   if closureIterResult != @expectedResults or exceptionCaught != exceptionExpected:
@@ -39,8 +38,8 @@ proc test(it: iterator(): int, expectedResults: varargs[int]) =
 proc testExc(it: iterator(): int, expectedResults: varargs[int]) =
   testClosureIterAux(it, true, expectedResults)
 
-proc raiseException() =
-  raise newException(TestException, "Test exception!")
+proc raiseTestError() =
+  raise newException(TestError, "Test exception!")
 
 block:
   iterator it(): int {.closure.} =
@@ -58,8 +57,8 @@ block:
     yield 0
     try:
       checkpoint(1)
-      raiseException()
-    except TestException:
+      raiseTestError()
+    except TestError:
       checkpoint(2)
       yield 3
       checkpoint(4)
@@ -89,7 +88,7 @@ block:
     yield 0
     try:
       yield 1
-      raiseException()
+      raiseTestError()
       yield 2
     finally:
       checkpoint(3)
@@ -103,8 +102,8 @@ block:
   iterator it(): int {.closure.} =
     try:
       try:
-        raiseException()
-      except AnotherException:
+        raiseTestError()
+      except AnotherError:
         yield 123
       finally:
         checkpoint(3)
@@ -117,8 +116,8 @@ block:
   iterator it(): int {.closure.} =
     try:
       yield 1
-      raiseException()
-    except AnotherException:
+      raiseTestError()
+    except AnotherError:
       checkpoint(123)
     finally:
       checkpoint(2)
@@ -134,12 +133,12 @@ block:
         yield 1
         try:
           yield 2
-          raiseException()
-        except AnotherException:
+          raiseTestError()
+        except AnotherError:
           yield 123
         finally:
           yield 3
-      except AnotherException:
+      except AnotherError:
         yield 124
       finally:
         yield 4
@@ -170,10 +169,10 @@ block:
     try:
       try:
         yield 0
-        raiseException()
+        raiseTestError()
       finally:
         checkpoint(1)
-    except TestException:
+    except TestError:
       yield 2
       return
     finally:
@@ -188,10 +187,10 @@ block:
     try:
       try:
         yield 0
-        raiseException()
+        raiseTestError()
       finally:
         return # Return in finally should stop exception propagation
-    except AnotherException:
+    except AnotherError:
       yield 2
       return
     finally:
@@ -228,9 +227,9 @@ block:
     var foo = 123
     let i = try:
         yield 0
-        raiseException()
+        raiseTestError()
         1
-      except TestException as e:
+      except TestError as e:
         assert(e.msg == "Test exception!")
         case foo
         of 1:
@@ -262,9 +261,9 @@ block:
     template tryexcept: int =
       try:
         yield 1
-        raiseException()
+        raiseTestError()
         123
-      except TestException:
+      except TestError:
         yield 2
         checkpoint(3)
         4
@@ -323,11 +322,11 @@ block:
     for i in 0 .. 1:
       try:
         yield 1
-        raiseException()
-      except TestException as e:
+        raiseTestError()
+      except TestError as e:
         doAssert(e.msg == "Test exception!")
         yield 2
-      except AnotherException:
+      except AnotherError:
         yield 123
       except:
         yield 1234
@@ -483,5 +482,48 @@ block: # nnkChckRange
 
   test(it, 1, 2, 3)
 
-echo "ok"
+block: #17849 - yield in case subject
+  template yieldInCase: int =
+    yield 2
+    3
+
+  iterator it(): int {.closure.} =
+    yield 1
+    case yieldInCase()
+    of 1: checkpoint(11)
+    of 3: checkpoint(13)
+    else: checkpoint(14)
+    yield 5
+
+  test(it, 1, 2, 13, 5)
 
+block: # void iterator
+  iterator it() {.closure.} =
+    try:
+      yield
+    except:
+      discard
+  var a = it
+
+if defined(nimOptIters): # Locals present in only 1 state should be on the stack
+  proc checkOnStack(a: pointer, shouldBeOnStack: bool) =
+    # Quick and dirty way to check if a points to stack
+    var dummy = 0
+    let dummyAddr = addr dummy
+    let distance = abs(cast[int](dummyAddr) - cast[int](a))
+    const requiredDistance = 300
+    if shouldBeOnStack:
+      doAssert(distance <= requiredDistance, "a is not on stack, but should")
+    else:
+      doAssert(distance > requiredDistance, "a is on stack, but should not")
+
+  iterator it(): int {.closure.} =
+    var a = 1
+    var b = 2
+    var c {.liftLocals.} = 3
+    checkOnStack(addr a, true)
+    checkOnStack(addr b, false)
+    checkOnStack(addr c, false)
+    yield a
+    yield b
+  test(it, 1, 2)