summary refs log tree commit diff stats
path: root/tests/closure
diff options
context:
space:
mode:
Diffstat (limited to 'tests/closure')
-rw-r--r--tests/closure/t11042.nim55
-rw-r--r--tests/closure/t15594.nim10
-rw-r--r--tests/closure/t1641.nim20
-rw-r--r--tests/closure/t19095.nim35
-rw-r--r--tests/closure/t20152.nim20
-rw-r--r--tests/closure/t8550.nim13
-rw-r--r--tests/closure/t9334.nim19
-rw-r--r--tests/closure/tboehmdeepcopy.nim18
-rw-r--r--tests/closure/tcapture.nim34
-rw-r--r--tests/closure/tclosure.nim523
-rw-r--r--tests/closure/tclosure0.nim87
-rw-r--r--tests/closure/tclosure2.nim101
-rw-r--r--tests/closure/tclosure3.nim21
-rw-r--r--tests/closure/tclosure4.nim13
-rw-r--r--tests/closure/tclosure_issues.nim82
-rw-r--r--tests/closure/tclosurebug2.nim194
-rw-r--r--tests/closure/tclosureinference3304.nim15
-rw-r--r--tests/closure/tcodegenerr1923.nim9
-rw-r--r--tests/closure/tdeeplynested.nim20
-rw-r--r--tests/closure/texplicit_dummy_closure.nim13
-rw-r--r--tests/closure/tfib50.nim22
-rw-r--r--tests/closure/tflatmap.nim24
-rw-r--r--tests/closure/tforum.nim44
-rw-r--r--tests/closure/tfutclosure2138.nim10
-rw-r--r--tests/closure/tinfer_closure_for_nestedproc.nim42
-rw-r--r--tests/closure/tinterf.nim24
-rw-r--r--tests/closure/tinvalidclosure.nim2
-rw-r--r--tests/closure/tinvalidclosure2.nim2
-rw-r--r--tests/closure/tinvalidclosure3.nim12
-rw-r--r--tests/closure/tinvalidclosure4.nim9
-rw-r--r--tests/closure/tinvalidclosure5.nim10
-rw-r--r--tests/closure/tissue1502def.nim6
-rw-r--r--tests/closure/tissue1642.nim3
-rw-r--r--tests/closure/tissue1846.nim16
-rw-r--r--tests/closure/tissue1911.nim7
-rw-r--r--tests/closure/tissue600.nim4
-rw-r--r--tests/closure/tjester.nim32
-rw-r--r--tests/closure/tmacrobust1512.nim222
-rw-r--r--tests/closure/tnamedparamanonproc.nim14
-rw-r--r--tests/closure/tnested.nim215
-rw-r--r--tests/closure/tnestedclosure.nim51
-rw-r--r--tests/closure/tnestedproc.nim12
-rw-r--r--tests/closure/tnoclosure.nim25
-rw-r--r--tests/closure/tstmtlist.nim9
-rw-r--r--tests/closure/ttimeinfo.nim15
45 files changed, 1218 insertions, 916 deletions
diff --git a/tests/closure/t11042.nim b/tests/closure/t11042.nim
new file mode 100644
index 000000000..6a3928316
--- /dev/null
+++ b/tests/closure/t11042.nim
@@ -0,0 +1,55 @@
+discard """
+  output:'''
+foo: 1
+foo: 2
+bar: 1
+bar: 2
+foo: 1
+foo: 2
+bar: 1
+bar: 2
+bar: 3
+bar: 4
+bar: 5
+bar: 6
+bar: 7
+bar: 8
+bar: 9
+'''
+"""
+
+# bug #11042
+block:
+  iterator foo: int =
+    for x in 1..2:
+      echo "foo: ", x
+      for y in 1..2:
+        discard
+
+  for x in foo(): discard
+
+  let bar = iterator: int =
+    for x in 1..2:
+      echo "bar: ", x
+      for y in 1..2:
+        discard
+
+  for x in bar(): discard
+
+
+block:
+  iterator foo: int =
+    for x in 1..2:
+      echo "foo: ", x
+      for y in 1..2:
+        discard
+
+  for x in foo(): discard
+
+  let bar = iterator: int =
+    for x in 1..9:
+      echo "bar: ", x
+      for y in 1..2:
+        discard
+
+  for x in bar(): discard
\ No newline at end of file
diff --git a/tests/closure/t15594.nim b/tests/closure/t15594.nim
new file mode 100644
index 000000000..aacd9ed84
--- /dev/null
+++ b/tests/closure/t15594.nim
@@ -0,0 +1,10 @@
+discard """
+  errormsg: "The variable name cannot be `result`!"
+"""
+
+import sugar
+
+proc begin(): int =
+  capture result:
+    echo 1+1
+  result
diff --git a/tests/closure/t1641.nim b/tests/closure/t1641.nim
new file mode 100644
index 000000000..a3e4da367
--- /dev/null
+++ b/tests/closure/t1641.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''foo 0
+bar 0
+baz'''
+"""
+
+# bug #1641
+proc baz() =
+  echo "baz"
+
+proc bar(x: int, p: proc()) =
+  echo "bar ", x
+  p()
+
+proc foo(x: int, p: proc(x: int)) =
+  echo "foo ", x
+  p(x)
+
+let x = 0
+x.foo do(x: int): x.bar do(): baz()
diff --git a/tests/closure/t19095.nim b/tests/closure/t19095.nim
new file mode 100644
index 000000000..880456e02
--- /dev/null
+++ b/tests/closure/t19095.nim
@@ -0,0 +1,35 @@
+discard """
+  action: compile
+"""
+
+block:
+  func inCheck() =
+    discard
+
+  iterator iter(): int =
+    yield 0
+    yield 0
+
+  func search() =
+    let inCheck = 0
+
+    for i in iter():
+
+      proc hello() =
+        inCheck()
+
+  search()
+block:
+  iterator iter(): int =
+    yield 0
+    yield 0
+
+  func search() =
+    let lmrMoveCounter = 0
+
+    for i in iter():
+
+      proc hello() =
+        discard lmrMoveCounter
+
+  search()
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()

diff --git a/tests/closure/t8550.nim b/tests/closure/t8550.nim
new file mode 100644
index 000000000..a07f45cdc
--- /dev/null
+++ b/tests/closure/t8550.nim
@@ -0,0 +1,13 @@
+discard """
+  targets: "c js"
+  output: "@[\"42\"]"
+"""
+
+proc chk_fail(): seq[string] =
+  iterator x(): int {.closure.} = yield 42
+  proc f(cl: iterator(): int {.closure.}): seq[string] =
+    result = @[]
+    for i in cl(): result.add($i)
+  result = f(x)
+
+echo(chk_fail())
diff --git a/tests/closure/t9334.nim b/tests/closure/t9334.nim
new file mode 100644
index 000000000..36a9a7d77
--- /dev/null
+++ b/tests/closure/t9334.nim
@@ -0,0 +1,19 @@
+discard """
+  cmd: "nim $target --hints:off $options -r $file"
+  nimout: '''@[1]
+@[1, 1]
+'''
+  nimoutFull: true
+"""
+proc p(s: var seq[int]): auto =
+  let sptr = addr s
+  return proc() = sptr[].add 1
+
+proc f =
+  var data = @[1]
+  p(data)()
+  echo repr data
+
+static:
+  f() # prints [1]
+f() # prints [1, 1]
diff --git a/tests/closure/tboehmdeepcopy.nim b/tests/closure/tboehmdeepcopy.nim
new file mode 100644
index 000000000..7c937ca10
--- /dev/null
+++ b/tests/closure/tboehmdeepcopy.nim
@@ -0,0 +1,18 @@
+discard """
+  cmd: "nim c --gc:boehm $options $file"
+  output: '''meep'''
+  disabled: "windows"
+"""
+
+proc callit(it: proc ()) =
+  it()
+
+proc main =
+  var outer = "meep"
+  proc x =
+    echo outer
+  var y: proc()
+  deepCopy(y, x)
+  callit(y)
+
+main()
diff --git a/tests/closure/tcapture.nim b/tests/closure/tcapture.nim
new file mode 100644
index 000000000..dafc44739
--- /dev/null
+++ b/tests/closure/tcapture.nim
@@ -0,0 +1,34 @@
+discard """
+  output: '''
+to be, or not to be
+(v: 1)
+(w: -1)
+(v: 1)
+(w: -1)
+'''
+  joinable: false
+"""
+
+import sequtils, sugar
+
+let m = @[proc (s: string): string = "to " & s, proc (s: string): string = "not to " & s]
+var l = m.mapIt(capture([it], proc (s: string): string = it(s)))
+let r = l.mapIt(it("be"))
+echo r[0] & ", or " & r[1]
+
+type
+  O = object
+    v: int
+  U = object
+    w: int
+var o = O(v: 1)
+var u = U(w: -1)
+var execute: proc()
+capture o, u:
+  execute = proc() =
+    echo o
+    echo u
+execute()
+o.v = -1
+u.w = 1
+execute()
diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim
index 09d48436e..401a71d40 100644
--- a/tests/closure/tclosure.nim
+++ b/tests/closure/tclosure.nim
@@ -1,47 +1,504 @@
 discard """
-  file: "tclosure.nim"
-  output: "1 3 6 11 20"
+  targets: "c"
+  output: '''
+1 3 6 11 20 foo
+foo88
+23 24foo 88
+18
+18
+99
+99
+99
+99 99
+99 99
+12 99 99
+12 99 99
+success
+@[1, 2, 5]
+click at 10,20
+lost focus 1
+lost focus 2
+registered handler for UserEvent 1
+registered handler for UserEvent 2
+registered handler for UserEvent 3
+registered handler for UserEvent 4
+asdas
+processClient end
+false
+baro0
+foo88
+23 24foo 88
+foo88
+23 24foo 88
+11
+@[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
+'''
+joinable: false
 """
-# Test the closure implementation
 
-proc map(n: var openarray[int], fn: proc (x: int): int {.closure}) =
-  for i in 0..n.len-1: n[i] = fn(n[i])
 
-proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int =
-  for i in 0..n.len-1:
-    result = fn(result, n[i])
+block tclosure:
+  proc map(n: var openArray[int], fn: proc (x: int): int {.closure}) =
+    for i in 0..n.len-1: n[i] = fn(n[i])
 
-proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
-  for i in 0..n.len-1:
-    fn(n[i])
+  proc each(n: openArray[int], fn: proc(x: int) {.closure.}) =
+    for i in 0..n.len-1:
+      fn(n[i])
 
-var
-  myData: array[0..4, int] = [0, 1, 2, 3, 4]
+  var myData: array[0..4, int] = [0, 1, 2, 3, 4]
 
-proc testA() =
-  var p = 0
-  map(myData, proc (x: int): int =
-                result = x + 1 shl (proc (y: int): int =
-                  return y + p
-                )(0)
-                inc(p))
+  proc testA() =
+    var p = 0
+    map(myData, proc (x: int): int =
+                  result = x + 1 shl (proc (y: int): int =
+                    return y + p
+                  )(0)
+                  inc(p))
 
-testA()
+  testA()
 
-myData.each do (x: int):
-  write(stdout, x)
-  write(stdout, " ")
+  myData.each do (x: int):
+    write(stdout, x)
+    write(stdout, " ")
 
-#OUT 2 4 6 8 10
+  #OUT 2 4 6 8 10
 
-type
-  ITest = tuple[
-    setter: proc(v: int),
-    getter: proc(): int]
+  # bug #5015
 
-proc getInterf(): ITest =
-  var shared: int
+  type Mutator = proc(matched: string): string {.noSideEffect, gcsafe.}
 
-  return (setter: proc (x: int) = shared = x,
-          getter: proc (): int = return shared)
+  proc putMutated(
+      MutatorCount: static[int],
+      mTable: static[array[MutatorCount, Mutator]], input: string) =
+    for i in 0..<MutatorCount: echo mTable[i](input)
 
+  proc mutator0(matched: string): string =
+      "foo"
+
+  const
+    mTable = [Mutator(mutator0)]
+
+  putMutated(1, mTable, "foo")
+
+
+
+block tclosure0:
+  when true:
+    # test simple closure within dummy 'main':
+    proc dummy =
+      proc main2(param: int) =
+        var fooB = 23
+        proc outer(outerParam: string) =
+          var outerVar = 88
+          echo outerParam, outerVar
+          proc inner() =
+            block Test:
+              echo fooB, " ", param, outerParam, " ", outerVar
+          inner()
+        outer("foo")
+      main2(24)
+
+    dummy()
+
+  when true:
+    proc outer2(x:int) : proc(y:int):int =   # curry-ed application
+        return proc(y:int):int = x*y
+
+    var fn = outer2(6)  # the closure
+    echo fn(3)   # it works
+
+    var rawP = fn.rawProc()
+    var rawE = fn.rawEnv()
+
+    # A type to cast the function pointer into a nimcall
+    type TimesClosure = proc(a: int, x: pointer): int {.nimcall.}
+
+    # Call the function with its closure
+    echo cast[TimesClosure](rawP)(3, rawE)
+
+  when true:
+    proc outer =
+      var x, y: int = 99
+      proc innerA = echo x
+      proc innerB =
+        echo y
+        innerA()
+
+      innerA()
+      innerB()
+
+    outer()
+
+  when true:
+    proc indirectDep =
+      var x, y: int = 99
+      proc innerA = echo x, " ", y
+      proc innerB =
+        innerA()
+
+      innerA()
+      innerB()
+
+    indirectDep()
+
+  when true:
+    proc needlessIndirection =
+      var x, y: int = 99
+      proc indirection =
+        var z = 12
+        proc innerA = echo z, " ", x, " ", y
+        proc innerB =
+          innerA()
+
+        innerA()
+        innerB()
+      indirection()
+
+    needlessIndirection()
+
+
+
+
+
+
+block tclosure3:
+  proc main =
+    const n = 30
+    for iterations in 0..10_000:
+      var s: seq[proc(): string {.closure.}] = @[]
+      for i in 0 .. n-1:
+        (proc () =
+          let ii = i
+          s.add(proc(): string = return $(ii*ii)))()
+      for i in 0 .. n-1:
+        let val = s[i]()
+        if val != $(i*i): echo "bug  ", val
+
+      if getOccupiedMem() > 5000_000: quit("still a leak!")
+    echo "success"
+
+  main()
+
+
+
+import json, tables, sequtils
+block tclosure4:
+  proc run(json_params: OrderedTable) =
+    let json_elems = json_params["files"].elems
+    # These fail compilation.
+    var files = map(json_elems, proc (x: JsonNode): string = x.str)
+
+  let text = """{"files": ["a", "b", "c"]}"""
+  run((text.parseJson).fields)
+
+
+
+import sugar
+block inference3304:
+  type
+    List[T] = ref object
+      val: T
+
+  proc foo[T](l: List[T]): seq[int] =
+    @[1,2,3,5].filter(x => x != l.val)
+
+  echo(foo(List[int](val: 3)))
+
+
+
+block tcodegenerr1923:
+  type
+    Foo[M] = proc() : M
+
+  proc bar[M](f : Foo[M]) =
+    discard f()
+
+  proc baz() : int = 42
+
+  bar(baz)
+
+
+
+block doNotation:
+  type
+    Button = object
+    Event = object
+      x, y: int
+
+  proc onClick(x: Button, handler: proc(x: Event)) =
+    handler(Event(x: 10, y: 20))
+
+  proc onFocusLost(x: Button, handler: proc()) =
+    handler()
+
+  proc onUserEvent(x: Button, eventName: string, handler: proc) =
+    echo "registered handler for ", eventName
+
+  var b = Button()
+
+  b.onClick do (e: Event):
+    echo "click at ", e.x, ",", e.y
+
+  b.onFocusLost do ():
+    echo "lost focus 1"
+
+  b.onFocusLost do ():
+    echo "lost focus 2"
+
+  b.onUserEvent("UserEvent 1") do ():
+    discard
+
+  onUserEvent(b, "UserEvent 2") do ():
+    discard
+
+  b.onUserEvent("UserEvent 3") do ():
+    discard
+
+  b.onUserEvent("UserEvent 4", () => echo "event 4")
+
+
+
+import tables
+block fib50:
+  proc memoize(f: proc (a: int64): int64): proc (a: int64): int64 =
+      var previous = initTable[int64, int64]()
+      return proc(i: int64): int64 =
+          if not previous.hasKey i:
+              previous[i] = f(i)
+          return previous[i]
+
+  var fib: proc(a: int64): int64
+
+  fib = memoize(proc (i: int64): int64 =
+      if i == 0 or i == 1:
+          return 1
+      return fib(i-1) + fib(i-2)
+  )
+
+  doAssert fib(50) == 20365011074
+
+
+
+block tflatmap:
+  # bug #3995
+  type
+    RNG = tuple[]
+    Rand[A] = (RNG) -> (A, RNG)
+
+  proc nextInt(r: RNG): (int, RNG) =
+    (1, ())
+
+  proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
+    (rng: RNG) => (
+      let (a, rng2) = f(rng);
+      let g1 = g(a);
+      g1(rng2)
+    )
+
+  proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
+    let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
+    flatMap(s, g)
+
+  discard nextInt.map(i => i - i mod 2)
+
+
+
+block tforum:
+  type
+    PAsyncHttpServer = ref object
+      value: string
+    PFutureBase = ref object
+      callback: proc () {.closure.}
+      value: string
+      failed: bool
+
+  proc accept(server: PAsyncHttpServer): PFutureBase =
+    new(result)
+    result.callback = proc () =
+      discard
+    server.value = "hahaha"
+
+  proc processClient(): PFutureBase =
+    new(result)
+
+  proc serve(server: PAsyncHttpServer): PFutureBase =
+    iterator serveIter(): PFutureBase {.closure.} =
+      echo server.value
+      while true:
+        var acceptAddrFut = server.accept()
+        yield acceptAddrFut
+        var fut = acceptAddrFut.value
+
+        var f = processClient()
+        f.callback =
+          proc () =
+            echo("processClient end")
+            echo(f.failed)
+        yield f
+    var x = serveIter
+    for i in 0 .. 1:
+      result = x()
+      result.callback()
+
+  discard serve(PAsyncHttpServer(value: "asdas"))
+
+
+
+block futclosure2138:
+  proc any[T](list: varargs[T], pred: (T) -> bool): bool =
+    for item in list:
+        if pred(item):
+            result = true
+            break
+
+  proc contains(s: string, words: varargs[string]): bool =
+    any(words, (word) => s.contains(word))
+
+
+
+block tinterf:
+  type
+    ITest = tuple[
+      setter: proc(v: int) {.closure.},
+      getter1: proc(): int {.closure.},
+      getter2: proc(): int {.closure.}]
+
+  proc getInterf(): ITest =
+    var shared1, shared2: int
+
+    return (setter: proc (x: int) =
+              shared1 = x
+              shared2 = x + 10,
+            getter1: proc (): int = result = shared1,
+            getter2: proc (): int = return shared2)
+
+  var i = getInterf()
+  i.setter(56)
+
+  doAssert i.getter1() == 56
+  doAssert i.getter2() == 66
+
+
+
+block tjester:
+  type
+    Future[T] = ref object
+      data: T
+      callback: proc () {.closure.}
+
+  proc cbOuter(response: string) {.discardable.} =
+    iterator cbIter(): Future[int] {.closure.} =
+      for i in 0..7:
+        proc foo(): int =
+          iterator fooIter(): Future[int] {.closure.} =
+            echo response, i
+            yield Future[int](data: 17)
+          var iterVar = fooIter
+          iterVar().data
+        yield Future[int](data: foo())
+
+    var iterVar2 = cbIter
+    proc cb2() {.closure.} =
+      try:
+        if not finished(iterVar2):
+          let next = iterVar2()
+          if next != nil:
+            next.callback = cb2
+      except:
+        echo "WTF"
+    cb2()
+
+  cbOuter "baro"
+
+
+
+block tnamedparamanonproc:
+  type
+    PButton = ref object
+    TButtonClicked = proc(button: PButton) {.nimcall.}
+
+  proc newButton(onClick: TButtonClicked) =
+    discard
+
+  proc main() =
+    newButton(onClick = proc(b: PButton) =
+      var requestomat = 12
+      )
+
+  main()
+
+
+
+block tnestedclosure:
+  proc main(param: int) =
+    var foo = 23
+    proc outer(outerParam: string) =
+      var outerVar = 88
+      echo outerParam, outerVar
+      proc inner() =
+        block Test:
+          echo foo, " ", param, outerParam, " ", outerVar
+      inner()
+    outer("foo")
+
+  # test simple closure within dummy 'main':
+  proc dummy =
+    proc main2(param: int) =
+      var fooB = 23
+      proc outer(outerParam: string) =
+        var outerVar = 88
+        echo outerParam, outerVar
+        proc inner() =
+          block Test:
+            echo fooB, " ", param, outerParam, " ", outerVar
+        inner()
+      outer("foo")
+    main2(24)
+
+  dummy()
+
+  main(24)
+
+  # Jester + async triggered this bug:
+  proc cbOuter() =
+    var response = "hohoho"
+    block:
+      proc cbIter() =
+        block:
+          proc fooIter() =
+            doAssert response == "hohoho"
+          fooIter()
+      cbIter()
+  cbOuter()
+
+
+
+block tnestedproc:
+  proc p(x, y: int): int =
+    result = x + y
+
+  echo p((proc (): int =
+            var x = 7
+            return x)(),
+         (proc (): int = return 4)())
+
+
+
+block tnoclosure:
+  proc pascal(n: int) =
+    var row = @[1]
+    for r in 1..n:
+      row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1])
+    echo row
+  pascal(10)
+
+block: # bug #22297
+  iterator f: int {.closure.} =
+    try:
+      yield 12
+    finally:
+      return 14
+
+  let s = f
+  doAssert s() == 12
+  doAssert s() == 14
diff --git a/tests/closure/tclosure0.nim b/tests/closure/tclosure0.nim
deleted file mode 100644
index 9952268d5..000000000
--- a/tests/closure/tclosure0.nim
+++ /dev/null
@@ -1,87 +0,0 @@
-discard """
-  output: '''foo88
-23 24foo 88
-18
-18
-99
-99
-99
-99 99
-99 99
-12 99 99
-12 99 99'''
-"""
-
-when true:
-  # test simple closure within dummy 'main':
-  proc dummy =
-    proc main2(param: int) =
-      var fooB = 23
-      proc outer(outerParam: string) =
-        var outerVar = 88
-        echo outerParam, outerVar
-        proc inner() =
-          block Test:
-            echo fooB, " ", param, outerParam, " ", outerVar
-        inner()
-      outer("foo")
-    main2(24)
-
-  dummy()
-
-when true:
-  proc outer2(x:int) : proc(y:int):int =   # curry-ed application
-      return proc(y:int):int = x*y
-
-  var fn = outer2(6)  # the closure
-  echo fn(3)   # it works
-
-  var rawP = fn.rawProc()
-  var rawE = fn.rawEnv()
-
-  # A type to cast the function pointer into a nimcall
-  type
-    TimesClosure = proc(a: int, x: pointer): int {.nimcall.}
-
-  # Call the function with its closure
-  echo cast[TimesClosure](rawP)(3, rawE)
-
-when true:
-  proc outer =
-    var x, y: int = 99
-    proc innerA = echo x
-    proc innerB =
-      echo y
-      innerA()
-
-    innerA()
-    innerB()
-
-  outer()
-
-when true:
-  proc indirectDep =
-    var x, y: int = 99
-    proc innerA = echo x, " ", y
-    proc innerB =
-      innerA()
-
-    innerA()
-    innerB()
-
-  indirectDep()
-
-when true:
-  proc needlessIndirection =
-    var x, y: int = 99
-    proc indirection =
-      var z = 12
-      proc innerA = echo z, " ", x, " ", y
-      proc innerB =
-        innerA()
-
-      innerA()
-      innerB()
-    indirection()
-
-  needlessIndirection()
diff --git a/tests/closure/tclosure2.nim b/tests/closure/tclosure2.nim
deleted file mode 100644
index 9c5ee1426..000000000
--- a/tests/closure/tclosure2.nim
+++ /dev/null
@@ -1,101 +0,0 @@
-discard """
-  output: '''0
-11
-1
-11
-2
-11
-3
-11
-4
-11
-5
-11
-6
-11
-7
-11
-8
-11
-9
-11
-11
-py
-py
-py
-py
-px
-6'''
-"""
-
-when true:
-  proc ax =
-    for xxxx in 0..9:
-      var i = 0
-      proc bx =
-        if i > 10:
-          echo xxxx
-          return
-        i += 1
-        #for j in 0 .. 0: echo i
-        bx()
-
-      bx()
-      echo i
-
-  ax()
-
-when true:
-  proc accumulator(start: int): (proc(): int {.closure.}) =
-    var x = start-1
-    #let dummy = proc =
-    #  discard start
-
-    result = proc (): int =
-      #var x = 9
-      for i in 0 .. 0: x = x + 1
-
-      return x
-
-  var a = accumulator(3)
-  let b = accumulator(4)
-  echo a() + b() + a()
-
-
-  proc outer =
-
-    proc py() =
-      # no closure here:
-      for i in 0..3: echo "py"
-
-    py()
-
-  outer()
-
-
-when true:
-  proc outer2 =
-    var errorValue = 3
-    proc fac[T](n: T): T =
-      if n < 0: result = errorValue
-      elif n <= 1: result = 1
-      else: result = n * fac(n-1)
-
-    proc px() {.closure.} =
-      echo "px"
-
-    proc py() {.closure.} =
-      echo "py"
-
-    let
-      mapping = {
-        "abc": px,
-        "xyz": py
-      }
-    mapping[0][1]()
-
-    echo fac(3)
-
-
-  outer2()
-
diff --git a/tests/closure/tclosure3.nim b/tests/closure/tclosure3.nim
deleted file mode 100644
index d5ffb5ab2..000000000
--- a/tests/closure/tclosure3.nim
+++ /dev/null
@@ -1,21 +0,0 @@
-discard """
-  file: "tclosure3.nim"
-  output: "success"
-"""
-
-proc main =
-  const n = 30
-  for iterations in 0..50_000:
-    var s: seq[proc(): string {.closure.}] = @[]
-    for i in 0 .. n-1:
-      (proc () =
-        let ii = i
-        s.add(proc(): string = return $(ii*ii)))()
-    for i in 0 .. n-1:
-      let val = s[i]()
-      if val != $(i*i): echo "bug  ", val
-
-    if getOccupiedMem() > 3000_000: quit("still a leak!")
-  echo "success"
-
-main()
diff --git a/tests/closure/tclosure4.nim b/tests/closure/tclosure4.nim
deleted file mode 100644
index 69c076cd5..000000000
--- a/tests/closure/tclosure4.nim
+++ /dev/null
@@ -1,13 +0,0 @@
-
-import json, tables, sequtils
-
-proc run(json_params: Table) =
-  let json_elems = json_params["files"].elems
-  # These fail compilation.
-  var files = map(json_elems, proc (x: JsonNode): string = x.str)
-  #var files = json_elems.map do (x: JsonNode) -> string: x.str
-  echo "Hey!"
-
-when isMainModule:
-  let text = """{"files": ["a", "b", "c"]}"""
-  run((text.parseJson).fields)
diff --git a/tests/closure/tclosure_issues.nim b/tests/closure/tclosure_issues.nim
new file mode 100644
index 000000000..b1a2d7c6b
--- /dev/null
+++ b/tests/closure/tclosure_issues.nim
@@ -0,0 +1,82 @@
+discard """
+  output: '''true
+(999, 0)
+ok 0
+ok 1
+ok 2
+'''
+"""
+
+
+block tissue600:
+  for i in 1..1:
+    var reported = false
+    proc report() =
+      reported = true
+
+
+
+import sequtils
+block tissue1502def:
+  let xs: seq[tuple[key: string, val: seq[string]]] = @[("foo", @["bar"])]
+
+  let maps = xs.map(
+    proc(x: auto): tuple[typ: string, maps: seq[string]] =
+      (x.key, x.val.map(proc(x: string): string = x)))
+
+
+
+block tissue1642:
+  var i = 0
+  proc p() = inc(i)
+
+
+
+block tissue1846:
+  type
+    TBinOp[T] = proc (x,y: T): bool
+    THeap[T] = object
+      cmp: TBinOp[T]
+
+  proc less[T](x,y: T): bool =
+    x < y
+
+  proc initHeap[T](cmp: TBinOp[T]): THeap[T] =
+    result.cmp = cmp
+
+  var h = initHeap[int](less[int])
+  echo h.cmp(2,3)
+
+
+
+block tissue1911:
+  proc foo(x: int) : auto =
+
+    proc helper() : int = x
+    proc bar() : int = helper()
+    proc baz() : int = helper()
+
+    return (bar, baz)
+
+# bug #11523
+proc foo(): proc =
+  let a = 999
+  return proc(): (int, int) =
+    return (a, 0)
+
+echo foo()()
+
+
+block tissue7104:
+  proc sp(cb: proc())=
+      cb()
+
+  sp do ():
+      var i = 0
+      echo "ok ", i
+      sp do ():
+          inc i
+          echo "ok ", i
+          sp do ():
+              inc i
+              echo "ok ", i
diff --git a/tests/closure/tclosurebug2.nim b/tests/closure/tclosurebug2.nim
deleted file mode 100644
index f131406a3..000000000
--- a/tests/closure/tclosurebug2.nim
+++ /dev/null
@@ -1,194 +0,0 @@
-import hashes, math
-
-type
-  TSlotEnum = enum seEmpty, seFilled, seDeleted
-  TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
-  TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
-
-  TOrderedKeyValuePair[A, B] = tuple[
-    slot: TSlotEnum, next: int, key: A, val: B]
-  TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]]
-  TOrderedTable*[A, B] = object ## table that remembers insertion order
-    data: TOrderedKeyValuePairSeq[A, B]
-    counter, first, last: int
-
-const
-  growthFactor = 2
-
-proc mustRehash(length, counter: int): bool {.inline.} =
-  assert(length > counter)
-  result = (length * 2 < counter * 3) or (length - counter < 4)
-
-proc nextTry(h, maxHash: Hash): Hash {.inline.} =
-  result = ((5 * h) + 1) and maxHash
-
-template rawGetImpl() {.dirty.} =
-  var h: Hash = hash(key) and high(t.data) # start with real hash value
-  while t.data[h].slot != seEmpty:
-    if t.data[h].key == key and t.data[h].slot == seFilled:
-      return h
-    h = nextTry(h, high(t.data))
-  result = -1
-
-template rawInsertImpl() {.dirty.} =
-  var h: Hash = hash(key) and high(data)
-  while data[h].slot == seFilled:
-    h = nextTry(h, high(data))
-  data[h].key = key
-  data[h].val = val
-  data[h].slot = seFilled
-
-template addImpl() {.dirty.} =
-  if mustRehash(len(t.data), t.counter): enlarge(t)
-  rawInsert(t, t.data, key, val)
-  inc(t.counter)
-
-template putImpl() {.dirty.} =
-  var index = rawGet(t, key)
-  if index >= 0:
-    t.data[index].val = val
-  else:
-    addImpl()
-
-proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} =
-  ## returns the number of keys in `t`.
-  result = t.counter
-
-template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
-  var h = t.first
-  while h >= 0:
-    var nxt = t.data[h].next
-    if t.data[h].slot == seFilled: yieldStmt
-    h = nxt
-
-iterator pairs*[A, B](t: TOrderedTable[A, B]): tuple[key: A, val: B] =
-  ## iterates over any (key, value) pair in the table `t` in insertion
-  ## order.
-  forAllOrderedPairs:
-    yield (t.data[h].key, t.data[h].val)
-
-iterator mpairs*[A, B](t: var TOrderedTable[A, B]): tuple[key: A, val: var B] =
-  ## iterates over any (key, value) pair in the table `t` in insertion
-  ## order. The values can be modified.
-  forAllOrderedPairs:
-    yield (t.data[h].key, t.data[h].val)
-
-iterator keys*[A, B](t: TOrderedTable[A, B]): A =
-  ## iterates over any key in the table `t` in insertion order.
-  forAllOrderedPairs:
-    yield t.data[h].key
-
-iterator values*[A, B](t: TOrderedTable[A, B]): B =
-  ## iterates over any value in the table `t` in insertion order.
-  forAllOrderedPairs:
-    yield t.data[h].val
-
-iterator mvalues*[A, B](t: var TOrderedTable[A, B]): var B =
-  ## iterates over any value in the table `t` in insertion order. The values
-  ## can be modified.
-  forAllOrderedPairs:
-    yield t.data[h].val
-
-proc rawGet[A, B](t: TOrderedTable[A, B], key: A): int =
-  rawGetImpl()
-
-proc `[]`*[A, B](t: TOrderedTable[A, B], key: A): B =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## default empty value for the type `B` is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
-  var index = rawGet(t, key)
-  if index >= 0: result = t.data[index].val
-
-proc mget*[A, B](t: var TOrderedTable[A, B], key: A): var B =
-  ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  var index = rawGet(t, key)
-  if index >= 0: result = t.data[index].val
-  else: raise newException(KeyError, "key not found: " & $key)
-
-proc hasKey*[A, B](t: TOrderedTable[A, B], key: A): bool =
-  ## returns true iff `key` is in the table `t`.
-  result = rawGet(t, key) >= 0
-
-proc rawInsert[A, B](t: var TOrderedTable[A, B],
-                     data: var TOrderedKeyValuePairSeq[A, B],
-                     key: A, val: B) =
-  rawInsertImpl()
-  data[h].next = -1
-  if t.first < 0: t.first = h
-  if t.last >= 0: data[t.last].next = h
-  t.last = h
-
-proc enlarge[A, B](t: var TOrderedTable[A, B]) =
-  var n: TOrderedKeyValuePairSeq[A, B]
-  newSeq(n, len(t.data) * growthFactor)
-  var h = t.first
-  t.first = -1
-  t.last = -1
-  while h >= 0:
-    var nxt = t.data[h].next
-    if t.data[h].slot == seFilled:
-      rawInsert(t, n, t.data[h].key, t.data[h].val)
-    h = nxt
-  swap(t.data, n)
-
-proc `[]=`*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
-  ## puts a (key, value)-pair into `t`.
-  putImpl()
-
-proc add*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
-  ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
-  addImpl()
-
-proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] =
-  ## creates a new ordered hash table that is empty. `initialSize` needs to be
-  ## a power of two.
-  assert isPowerOfTwo(initialSize)
-  result.counter = 0
-  result.first = -1
-  result.last = -1
-  newSeq(result.data, initialSize)
-
-proc toOrderedTable*[A, B](pairs: openarray[tuple[key: A,
-                           val: B]]): TOrderedTable[A, B] =
-  ## creates a new ordered hash table that contains the given `pairs`.
-  result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
-  for key, val in items(pairs): result[key] = val
-
-proc sort*[A, B](t: var TOrderedTable[A,B],
-                 cmp: proc (x, y: tuple[key: A, val: B]): int {.closure.}) =
-  ## sorts the ordered table so that the entry with the highest counter comes
-  ## first. This is destructive (with the advantage of being efficient)!
-  ## You must not modify `t` afterwards!
-  ## You can use the iterators `pairs`,  `keys`, and `values` to iterate over
-  ## `t` in the sorted order.
-
-  # we use shellsort here; fast enough and simple
-  var h = 1
-  while true:
-    h = 3 * h + 1
-    if h >= high(t.data): break
-  while true:
-    h = h div 3
-    for i in countup(h, high(t.data)):
-      var j = i
-      #echo(t.data.len, " ", j, " - ", h)
-      #echo(repr(t.data[j-h]))
-      proc rawCmp(x, y: TOrderedKeyValuePair[A, B]): int =
-        if x.slot in {seEmpty, seDeleted} and y.slot in {seEmpty, seDeleted}:
-          return 0
-        elif x.slot in {seEmpty, seDeleted}:
-          return -1
-        elif y.slot in {seEmpty, seDeleted}:
-          return 1
-        else:
-          let item1 = (x.key, x.val)
-          let item2 = (y.key, y.val)
-          return cmp(item1, item2)
-
-      while rawCmp(t.data[j-h], t.data[j]) <= 0:
-        swap(t.data[j], t.data[j-h])
-        j = j-h
-        if j < h: break
-    if h == 1: break
diff --git a/tests/closure/tclosureinference3304.nim b/tests/closure/tclosureinference3304.nim
deleted file mode 100644
index db4aa1d04..000000000
--- a/tests/closure/tclosureinference3304.nim
+++ /dev/null
@@ -1,15 +0,0 @@
-discard """
-  output: '''@[1, 2, 5]'''
-"""
-
-import future, sequtils
-
-type
-  List[T] = ref object
-    val: T
-  
-proc foo[T](l: List[T]): seq[int] =
-  @[1,2,3,5].filter(x => x != l.val)
-
-when isMainModule:
-  echo(foo(List[int](val: 3)))
diff --git a/tests/closure/tcodegenerr1923.nim b/tests/closure/tcodegenerr1923.nim
deleted file mode 100644
index ee131ae15..000000000
--- a/tests/closure/tcodegenerr1923.nim
+++ /dev/null
@@ -1,9 +0,0 @@
-type
-  Foo[M] = proc() : M
-
-proc bar[M](f : Foo[M]) =
-  discard f()
-
-proc baz() : int = 42
-
-bar(baz)
\ No newline at end of file
diff --git a/tests/closure/tdeeplynested.nim b/tests/closure/tdeeplynested.nim
deleted file mode 100644
index ddf4fa6a4..000000000
--- a/tests/closure/tdeeplynested.nim
+++ /dev/null
@@ -1,20 +0,0 @@
-discard """
-  output: '''int: 108'''
-"""
-
-# bug #4070
-
-proc id(f: (proc())): auto =
-  return f
-
-proc foo(myinteger: int): (iterator(): int) =
-  return iterator(): int {.closure.} =
-           proc bar() =
-             proc kk() =
-               echo "int: ", myinteger
-
-             kk()
-
-           id(bar)()
-
-discard foo(108)()
diff --git a/tests/closure/texplicit_dummy_closure.nim b/tests/closure/texplicit_dummy_closure.nim
index ec608b31a..02b9ac7c7 100644
--- a/tests/closure/texplicit_dummy_closure.nim
+++ b/tests/closure/texplicit_dummy_closure.nim
@@ -1,3 +1,6 @@
+discard """
+  disabled: true
+"""
 
 # This is a regression of the new lambda lifting; detected by Aporia
 import asyncio, sockets
@@ -5,8 +8,8 @@ import os
 
 type
   Window = object
-    oneInstSock*: PAsyncSocket
-    IODispatcher*: PDispatcher
+    oneInstSock*: AsyncSocket
+    IODispatcher*: Dispatcher
 
 var
   win: Window
@@ -14,9 +17,9 @@ var
 proc initSocket() =
   win.oneInstSock = asyncSocket()
   #win.oneInstSock.handleAccept =
-  proc test(s: PAsyncSocket) =
-    var client: PAsyncSocket
-    proc dummy(c: PAsyncSocket) {.closure.} =
+  proc test(s: AsyncSocket) =
+    var client: AsyncSocket
+    proc dummy(c: AsyncSocket) {.closure.} =
       discard
     client.handleRead = dummy
   test(win.oneInstSock)
diff --git a/tests/closure/tfib50.nim b/tests/closure/tfib50.nim
deleted file mode 100644
index 719aa3ad5..000000000
--- a/tests/closure/tfib50.nim
+++ /dev/null
@@ -1,22 +0,0 @@
-discard """
-  output: "20365011074"
-"""
-
-import tables
-
-proc memoize(f: proc (a: int64): int64): proc (a: int64): int64 =
-    var previous = initTable[int64, int64]()
-    return proc(i: int64): int64 =
-        if not previous.hasKey i:
-            previous[i] = f(i)
-        return previous[i]
-
-var fib: proc(a: int64): int64
-
-fib = memoize(proc (i: int64): int64 =
-    if i == 0 or i == 1:
-        return 1
-    return fib(i-1) + fib(i-2)
-)
-
-echo fib(50)
diff --git a/tests/closure/tflatmap.nim b/tests/closure/tflatmap.nim
deleted file mode 100644
index 240756424..000000000
--- a/tests/closure/tflatmap.nim
+++ /dev/null
@@ -1,24 +0,0 @@
-
-# bug #3995
-
-import future
-
-type
-  RNG* = tuple[]
-  Rand*[A] = (RNG) -> (A, RNG)
-
-proc nextInt*(r: RNG): (int, RNG) =
-  (1, ())
-
-proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
-  (rng: RNG) => (
-    let (a, rng2) = f(rng);
-    let g1 = g(a);
-    g1(rng2)
-  )
-
-proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
-  let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
-  flatMap(s, g)
-
-let f = nextInt.map(i => i - i mod 2)
diff --git a/tests/closure/tforum.nim b/tests/closure/tforum.nim
deleted file mode 100644
index 4f6a16ff7..000000000
--- a/tests/closure/tforum.nim
+++ /dev/null
@@ -1,44 +0,0 @@
-discard """
-  output: '''asdas
-processClient end
-false
-'''
-"""
-
-type
-  PAsyncHttpServer = ref object
-    value: string
-  PFutureBase = ref object
-    callback: proc () {.closure.}
-    value: string
-    failed: bool
-
-proc accept(server: PAsyncHttpServer): PFutureBase =
-  new(result)
-  result.callback = proc () =
-    discard
-  server.value = "hahaha"
-
-proc processClient(): PFutureBase =
-  new(result)
-
-proc serve(server: PAsyncHttpServer): PFutureBase =
-  iterator serveIter(): PFutureBase {.closure.} =
-    echo server.value
-    while true:
-      var acceptAddrFut = server.accept()
-      yield acceptAddrFut
-      var fut = acceptAddrFut.value
-
-      var f = processClient()
-      f.callback =
-        proc () =
-          echo("processClient end")
-          echo(f.failed)
-      yield f
-  var x = serveIter
-  for i in 0 .. 1:
-    result = x()
-    result.callback()
-
-discard serve(PAsyncHttpServer(value: "asdas"))
diff --git a/tests/closure/tfutclosure2138.nim b/tests/closure/tfutclosure2138.nim
deleted file mode 100644
index e18834074..000000000
--- a/tests/closure/tfutclosure2138.nim
+++ /dev/null
@@ -1,10 +0,0 @@
-import future, sequtils
-
-proc any[T](list: varargs[T], pred: (T) -> bool): bool =
-    for item in list:
-        if pred(item):
-            result = true
-            break
-
-proc contains(s: string, words: varargs[string]): bool =
-  any(words, (word) => s.contains(word))
\ No newline at end of file
diff --git a/tests/closure/tinfer_closure_for_nestedproc.nim b/tests/closure/tinfer_closure_for_nestedproc.nim
new file mode 100644
index 000000000..6450d1492
--- /dev/null
+++ b/tests/closure/tinfer_closure_for_nestedproc.nim
@@ -0,0 +1,42 @@
+discard """
+  action: compile
+"""
+
+# bug #9441
+import asyncdispatch, asyncfutures, strtabs
+
+type
+  Request = object
+  Context = object
+    position: int
+    accept: bool
+    headers: StringTableRef
+  Handler = proc (r: ref Request, c: Context): Future[Context]
+
+proc respond(req: Request): Future[void] = discard
+
+proc handle*(h: Handler): auto = # (proc (req: Request): Future[void]) =
+  proc server(req: Request): Future[void] {.async.} =
+    let emptyCtx = Context(
+      position: 0,
+      accept: true,
+      headers: newStringTable()
+    )
+    var reqHeap = new(Request)
+    reqHeap[] = req
+    var
+      f: Future[Context]
+      ctx: Context
+    try:
+      f = h(reqHeap, emptyCtx)
+      ctx = await f
+    except:
+      discard
+    if f.failed:
+      await req.respond()
+    else:
+      if not ctx.accept:
+        await req.respond()
+  return server
+
+waitFor handle(nil)(Request())
diff --git a/tests/closure/tinterf.nim b/tests/closure/tinterf.nim
deleted file mode 100644
index 1ac6da945..000000000
--- a/tests/closure/tinterf.nim
+++ /dev/null
@@ -1,24 +0,0 @@
-discard """
-  output: '''56 66'''
-"""
-
-type
-  ITest = tuple[
-    setter: proc(v: int) {.closure.},
-    getter1: proc(): int {.closure.},
-    getter2: proc(): int {.closure.}]
-
-proc getInterf(): ITest =
-  var shared1, shared2: int
-
-  return (setter: proc (x: int) =
-            shared1 = x
-            shared2 = x + 10,
-          getter1: proc (): int = result = shared1,
-          getter2: proc (): int = return shared2)
-
-var i = getInterf()
-i.setter(56)
-
-echo i.getter1(), " ", i.getter2()
-
diff --git a/tests/closure/tinvalidclosure.nim b/tests/closure/tinvalidclosure.nim
index d3f38cde5..37d0f68a2 100644
--- a/tests/closure/tinvalidclosure.nim
+++ b/tests/closure/tinvalidclosure.nim
@@ -1,6 +1,6 @@
 discard """
+  errormsg: "type mismatch: got <proc (x: int){.nimcall, gcsafe.}>"
   line: 12
-  errormsg: "type mismatch: got (proc (x: int){.gcsafe, locks: 0.})"
 """
 
 proc ugh[T](x: T) {.nimcall.} =
diff --git a/tests/closure/tinvalidclosure2.nim b/tests/closure/tinvalidclosure2.nim
index 845559309..2d58f0215 100644
--- a/tests/closure/tinvalidclosure2.nim
+++ b/tests/closure/tinvalidclosure2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: "illegal capture 'A'"
+  line: 10
 """
 
 proc outer() =
diff --git a/tests/closure/tinvalidclosure3.nim b/tests/closure/tinvalidclosure3.nim
new file mode 100644
index 000000000..0cbdaf39e
--- /dev/null
+++ b/tests/closure/tinvalidclosure3.nim
@@ -0,0 +1,12 @@
+discard """
+  errormsg: "illegal capture 'x'"
+  line: 9
+"""
+
+proc outer(arg: string) =
+  var x = 0
+  proc inner {.inline.} =
+    echo "inner", x
+  inner()
+
+outer("abc")
diff --git a/tests/closure/tinvalidclosure4.nim b/tests/closure/tinvalidclosure4.nim
new file mode 100644
index 000000000..7985a2488
--- /dev/null
+++ b/tests/closure/tinvalidclosure4.nim
@@ -0,0 +1,9 @@
+discard """
+  errormsg: "illegal capture 'v'"
+  line: 7
+"""
+
+proc outer(v: int) =
+  proc b {.nimcall.} = echo v
+  b()
+outer(5)
diff --git a/tests/closure/tinvalidclosure5.nim b/tests/closure/tinvalidclosure5.nim
new file mode 100644
index 000000000..3b5f46a40
--- /dev/null
+++ b/tests/closure/tinvalidclosure5.nim
@@ -0,0 +1,10 @@
+discard """
+  errormsg: "type mismatch: got <proc (){.closure, gcsafe.}> but expected 'A = proc (){.nimcall.}'"
+  line: 9
+"""
+
+type A = proc() {.nimcall.}
+proc main =
+  let b = 1
+  let a: A = proc() = echo b
+
diff --git a/tests/closure/tissue1502def.nim b/tests/closure/tissue1502def.nim
deleted file mode 100644
index 0aa6b16e3..000000000
--- a/tests/closure/tissue1502def.nim
+++ /dev/null
@@ -1,6 +0,0 @@
-import sequtils
-let xs: seq[tuple[key: string, val: seq[string]]] = @[("foo", @["bar"])]
-
-let maps = xs.map(
-  proc(x: auto): tuple[typ: string, maps: seq[string]] =
-    (x.key, x.val.map(proc(x: string): string = x)))
\ No newline at end of file
diff --git a/tests/closure/tissue1642.nim b/tests/closure/tissue1642.nim
deleted file mode 100644
index 5b921fc05..000000000
--- a/tests/closure/tissue1642.nim
+++ /dev/null
@@ -1,3 +0,0 @@
-block:
-    var i = 0
-    proc p() = inc(i)
\ No newline at end of file
diff --git a/tests/closure/tissue1846.nim b/tests/closure/tissue1846.nim
deleted file mode 100644
index 3fbef169d..000000000
--- a/tests/closure/tissue1846.nim
+++ /dev/null
@@ -1,16 +0,0 @@
-type
-    TBinOp*[T] = proc (x,y: T): bool
-
-    THeap*[T] = object
-        cmp*:   TBinOp[T]
-
-proc less*[T](x,y: T): bool =
-    x < y
-
-proc initHeap*[T](cmp: TBinOp[T]): THeap[T] =
-    result.cmp = cmp
-
-when isMainModule:
-    var h = initHeap[int](less[int])
-
-    echo h.cmp(2,3)
\ No newline at end of file
diff --git a/tests/closure/tissue1911.nim b/tests/closure/tissue1911.nim
deleted file mode 100644
index 311d99134..000000000
--- a/tests/closure/tissue1911.nim
+++ /dev/null
@@ -1,7 +0,0 @@
-proc foo(x: int) : auto =
-
-  proc helper() : int = x
-  proc bar() : int = helper()
-  proc baz() : int = helper()
-
-  return (bar, baz)
\ No newline at end of file
diff --git a/tests/closure/tissue600.nim b/tests/closure/tissue600.nim
deleted file mode 100644
index eacc7a123..000000000
--- a/tests/closure/tissue600.nim
+++ /dev/null
@@ -1,4 +0,0 @@
-for i in 1..1:
-  var reported = false
-  proc report() =
-    reported = true
\ No newline at end of file
diff --git a/tests/closure/tjester.nim b/tests/closure/tjester.nim
deleted file mode 100644
index 84e0fcb71..000000000
--- a/tests/closure/tjester.nim
+++ /dev/null
@@ -1,32 +0,0 @@
-discard """
-  output: '''baro0'''
-"""
-
-type
-  Future[T] = ref object
-    data: T
-    callback: proc () {.closure.}
-
-proc cbOuter(response: string) {.discardable.} =
-  iterator cbIter(): Future[int] {.closure.} =
-    for i in 0..7:
-      proc foo(): int =
-        iterator fooIter(): Future[int] {.closure.} =
-          echo response, i
-          yield Future[int](data: 17)
-        var iterVar = fooIter
-        iterVar().data
-      yield Future[int](data: foo())
-
-  var iterVar2 = cbIter
-  proc cb2() {.closure.} =
-    try:
-      if not finished(iterVar2):
-        let next = iterVar2()
-        if next != nil:
-          next.callback = cb2
-    except:
-      echo "WTF"
-  cb2()
-
-cbOuter "baro"
diff --git a/tests/closure/tmacrobust1512.nim b/tests/closure/tmacrobust1512.nim
index 95681e750..0f44c5e1a 100644
--- a/tests/closure/tmacrobust1512.nim
+++ b/tests/closure/tmacrobust1512.nim
@@ -1,115 +1,110 @@
+discard """
+output: ""
+"""
+
 import macros, strutils
 
 # https://github.com/nim-lang/Nim/issues/1512
 
-proc macrobust0 (raw_input: string) =
+proc macrobust0(input: string): string =
   var output = ""
-  proc p1 (a:string) =
-    output.add (a)
-
-  proc p2 (a:string) = p1 (a)
-  proc p3 (a:string) = p2 (a)
-  proc p4 (a:string) = p3 (a)
-  proc p5 (a:string) = p4 (a)
-  proc p6 (a:string) = p5 (a)
-  proc p7 (a:string) = p6 (a)
-  proc p8 (a:string) = p7 (a)
-  proc p9 (a:string) = p8 (a)
-  proc p10 (a:string) = p9 (a)
-  proc p11 (a:string) = p10 (a)
-  proc p12 (a:string) = p11 (a)
-  proc p13 (a:string) = p12 (a)
-  proc p14 (a:string) = p13 (a)
-  proc p15 (a:string) = p14 (a)
-  proc p16 (a:string) = p15 (a)
-  proc p17 (a:string) = p16 (a)
-  proc p18 (a:string) = p17 (a)
-  proc p19 (a:string) = p18 (a)
-  proc p20 (a:string) = p19 (a)
-
-  let input = $raw_input
-
-  for a in input.split ():
-    p20 (a)
-    p19 (a)
-
-
-    p18 (a)
-    p17 (a)
-    p16 (a)
-    p15 (a)
-    p14 (a)
-    p13 (a)
-    p12 (a)
-    p11 (a)
-    p10 (a)
-    p9 (a)
-    p8 (a)
-    p7 (a)
-    p6 (a)
-    p5 (a)
-    p4 (a)
-    p3 (a)
-    p2 (a)
-    p1 (a)
-
-
-  echo output
-
-macro macrobust (raw_input: expr) : stmt =
-
+  proc p1(a:string) =
+    output.add(a)
+
+  proc p2(a:string) = p1(a)
+  proc p3(a:string) = p2(a)
+  proc p4(a:string) = p3(a)
+  proc p5(a:string) = p4(a)
+  proc p6(a:string) = p5(a)
+  proc p7(a:string) = p6(a)
+  proc p8(a:string) = p7(a)
+  proc p9(a:string) = p8(a)
+  proc p10(a:string) = p9(a)
+  proc p11(a:string) = p10(a)
+  proc p12(a:string) = p11(a)
+  proc p13(a:string) = p12(a)
+  proc p14(a:string) = p13(a)
+  proc p15(a:string) = p14(a)
+  proc p16(a:string) = p15(a)
+  proc p17(a:string) = p16(a)
+  proc p18(a:string) = p17(a)
+  proc p19(a:string) = p18(a)
+  proc p20(a:string) = p19(a)
+
+  for a in input.split():
+    p20(a)
+    p19(a)
+    p18(a)
+    p17(a)
+    p16(a)
+    p15(a)
+    p14(a)
+    p13(a)
+    p12(a)
+    p11(a)
+    p10(a)
+    p9(a)
+    p8(a)
+    p7(a)
+    p6(a)
+    p5(a)
+    p4(a)
+    p3(a)
+    p2(a)
+    p1(a)
+
+  result = output
+
+macro macrobust(input: static[string]): untyped =
   var output = ""
-  proc p1 (a:string) =
-    output.add (a)
-
-  proc p2 (a:string) = p1 (a)
-  proc p3 (a:string) = p2 (a)
-  proc p4 (a:string) = p3 (a)
-  proc p5 (a:string) = p4 (a)
-  proc p6 (a:string) = p5 (a)
-  proc p7 (a:string) = p6 (a)
-  proc p8 (a:string) = p7 (a)
-  proc p9 (a:string) = p8 (a)
-  proc p10 (a:string) = p9 (a)
-  proc p11 (a:string) = p10 (a)
-  proc p12 (a:string) = p11 (a)
-  proc p13 (a:string) = p12 (a)
-  proc p14 (a:string) = p13 (a)
-  proc p15 (a:string) = p14 (a)
-  proc p16 (a:string) = p15 (a)
-  proc p17 (a:string) = p16 (a)
-  proc p18 (a:string) = p17 (a)
-  proc p19 (a:string) = p18 (a)
-  proc p20 (a:string) = p19 (a)
-
-  let input = $raw_input
-
-  for a in input.split ():
-    p20 (a)
-    p19 (a)
-
-    p18 (a)
-    p17 (a)
-    p16 (a)
-    p15 (a)
-    p14 (a)
-    p13 (a)
-    p12 (a)
-    p11 (a)
-    p10 (a)
-    p9 (a)
-    p8 (a)
-    p7 (a)
-    p6 (a)
-    p5 (a)
-    p4 (a)
-    p3 (a)
-    p2 (a)
-
-  echo output
-  discard result
-
-macrobust """
+  proc p1(a:string) =
+    output.add(a)
+
+  proc p2(a:string) = p1(a)
+  proc p3(a:string) = p2(a)
+  proc p4(a:string) = p3(a)
+  proc p5(a:string) = p4(a)
+  proc p6(a:string) = p5(a)
+  proc p7(a:string) = p6(a)
+  proc p8(a:string) = p7(a)
+  proc p9(a:string) = p8(a)
+  proc p10(a:string) = p9(a)
+  proc p11(a:string) = p10(a)
+  proc p12(a:string) = p11(a)
+  proc p13(a:string) = p12(a)
+  proc p14(a:string) = p13(a)
+  proc p15(a:string) = p14(a)
+  proc p16(a:string) = p15(a)
+  proc p17(a:string) = p16(a)
+  proc p18(a:string) = p17(a)
+  proc p19(a:string) = p18(a)
+  proc p20(a:string) = p19(a)
+
+  for a in input.split():
+    p20(a)
+    p19(a)
+    p18(a)
+    p17(a)
+    p16(a)
+    p15(a)
+    p14(a)
+    p13(a)
+    p12(a)
+    p11(a)
+    p10(a)
+    p9(a)
+    p8(a)
+    p7(a)
+    p6(a)
+    p5(a)
+    p4(a)
+    p3(a)
+    p2(a)
+    p1(a)
+
+  result = newLit(output)
+
+const input = """
   fdsasadfsdfa sadfsdafsdaf
   dsfsdafdsfadsfa fsdaasdfasdf
   fsdafsadfsad asdfasdfasdf
@@ -122,16 +117,7 @@ macrobust """
   sdfasdafsadf sdfasdafsdaf sdfasdafsdaf
 """
 
+let str1 = macrobust(input)
+let str2 = macrobust0(input)
 
-macrobust0 """
-  fdsasadfsdfa sadfsdafsdaf
-  dsfsdafdsfadsfa fsdaasdfasdf
-  fsdafsadfsad asdfasdfasdf
-  fdsasdfasdfa sadfsadfsadf
-  sadfasdfsdaf sadfsdafsdaf dsfasdaf
-  sadfsdafsadf fdsasdafsadf fdsasadfsdaf
-  sdfasadfsdafdfsa sadfsadfsdaf
-  sdafsdaffsda sdfasadfsadf
-  fsdasdafsdfa sdfasdfafsda
-  sdfasdafsadf sdfasdafsdaf sdfasdafsdaf
-"""
\ No newline at end of file
+doAssert str1 == str2
diff --git a/tests/closure/tnamedparamanonproc.nim b/tests/closure/tnamedparamanonproc.nim
deleted file mode 100644
index 94e32894f..000000000
--- a/tests/closure/tnamedparamanonproc.nim
+++ /dev/null
@@ -1,14 +0,0 @@
-
-type
-  PButton = ref object
-  TButtonClicked = proc(button: PButton) {.nimcall.}
-
-proc newButton*(onClick: TButtonClicked) =
-  discard
-
-proc main() =
-  newButton(onClick = proc(b: PButton) =
-    var requestomat = 12
-    )
-
-main()
diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim
new file mode 100644
index 000000000..ec5af9b13
--- /dev/null
+++ b/tests/closure/tnested.nim
@@ -0,0 +1,215 @@
+discard """
+targets: "c js"
+output: '''
+foo88
+23 24foo 88
+foo88
+23 24foo 88
+11
+int: 108
+0
+11
+1
+11
+2
+11
+3
+11
+4
+11
+5
+11
+6
+11
+7
+11
+8
+11
+9
+11
+11
+py
+py
+py
+py
+px
+6
+proc (){.closure, noSideEffect, gcsafe.}
+'''
+"""
+
+
+block tnestedclosure:
+  proc main(param: int) =
+    var foo = 23
+    proc outer(outerParam: string) =
+      var outerVar = 88
+      echo outerParam, outerVar
+      proc inner() =
+        block Test:
+          echo foo, " ", param, outerParam, " ", outerVar
+      inner()
+    outer("foo")
+
+  # test simple closure within dummy 'main':
+  proc dummy =
+    proc main2(param: int) =
+      var fooB = 23
+      proc outer(outerParam: string) =
+        var outerVar = 88
+        echo outerParam, outerVar
+        proc inner() =
+          block Test:
+            echo fooB, " ", param, outerParam, " ", outerVar
+        inner()
+      outer("foo")
+    main2(24)
+
+  dummy()
+
+  main(24)
+
+  # Jester + async triggered this bug:
+  proc cbOuter() =
+    var response = "hohoho"
+    block:
+      proc cbIter() =
+        block:
+          proc fooIter() =
+            doAssert response == "hohoho"
+          fooIter()
+      cbIter()
+  cbOuter()
+
+
+block tnestedproc:
+  proc p(x, y: int): int =
+    result = x + y
+
+  echo p((proc (): int =
+            var x = 7
+            return x)(),
+         (proc (): int = return 4)())
+
+
+block deeplynested:
+  # bug #4070
+  proc id(f: (proc())): auto =
+    return f
+
+  proc foo(myinteger: int): (iterator(): int) =
+    return iterator(): int {.closure.} =
+            proc bar() =
+              proc kk() =
+                echo "int: ", myinteger
+              kk()
+            id(bar)()
+
+  discard foo(108)()
+
+
+block tclosure2:
+  when true:
+    proc ax =
+      for xxxx in 0..9:
+        var i = 0
+        proc bx =
+          if i > 10:
+            echo xxxx
+            return
+          i += 1
+          #for j in 0 .. 0: echo i
+          bx()
+
+        bx()
+        echo i
+
+    ax()
+
+  when true:
+    proc accumulator(start: int): (proc(): int {.closure.}) =
+      var x = start-1
+      #let dummy = proc =
+      #  discard start
+
+      result = proc (): int =
+        #var x = 9
+        for i in 0 .. 0: x = x + 1
+
+        return x
+
+    var a = accumulator(3)
+    let b = accumulator(4)
+    echo a() + b() + a()
+
+
+    proc outer =
+
+      proc py() =
+        # no closure here:
+        for i in 0..3: echo "py"
+
+      py()
+
+    outer()
+
+
+  when true:
+    proc outer2 =
+      var errorValue = 3
+      proc fac[T](n: T): T =
+        if n < 0: result = errorValue
+        elif n <= 1: result = 1
+        else: result = n * fac(n-1)
+
+      proc px() {.closure.} =
+        echo "px"
+
+      proc py() {.closure.} =
+        echo "py"
+
+      let
+        mapping = {
+          "abc": px,
+          "xyz": py
+        }
+      mapping[0][1]()
+
+      echo fac(3)
+
+
+    outer2()
+
+# bug #5688
+
+import typetraits
+
+block:
+  proc myDiscard[T](a: T) = discard
+
+  proc foo() =
+    let a = 5
+    let f = (proc() =
+              myDiscard (proc() = echo a)
+            )
+    echo name(typeof(f))
+
+  foo()
+
+
+block:
+  iterator foo: int {.closure.} =
+    yield 1
+    yield 2
+    yield 3
+
+  proc pork =
+    let call = foo
+    for i in call():
+      discard i
+
+    let call2 = foo
+    while not finished(call2):
+      discard call2()
+
+  pork()
diff --git a/tests/closure/tnestedclosure.nim b/tests/closure/tnestedclosure.nim
deleted file mode 100644
index 0628a6977..000000000
--- a/tests/closure/tnestedclosure.nim
+++ /dev/null
@@ -1,51 +0,0 @@
-discard """
-  output: '''foo88
-23 24foo 88
-foo88
-23 24foo 88
-hohoho'''
-"""
-
-# test nested closure
-proc main(param: int) =
-  var foo = 23
-  proc outer(outerParam: string) =
-    var outerVar = 88
-    echo outerParam, outerVar
-    proc inner() =
-      block Test:
-        echo foo, " ", param, outerParam, " ", outerVar
-    inner()
-  outer("foo")
-
-# test simple closure within dummy 'main':
-proc dummy =
-  proc main2(param: int) =
-    var fooB = 23
-    proc outer(outerParam: string) =
-      var outerVar = 88
-      echo outerParam, outerVar
-      proc inner() =
-        block Test:
-          echo fooB, " ", param, outerParam, " ", outerVar
-      inner()
-    outer("foo")
-  main2(24)
-
-dummy()
-
-main(24)
-
-# Jester + async triggered this bug:
-proc cbOuter() =
-  var response = "hohoho"
-  block:
-    proc cbIter() =
-      block:
-        proc fooIter() =
-          echo response
-        fooIter()
-
-    cbIter()
-
-cbOuter()
diff --git a/tests/closure/tnestedproc.nim b/tests/closure/tnestedproc.nim
deleted file mode 100644
index 7eeeff198..000000000
--- a/tests/closure/tnestedproc.nim
+++ /dev/null
@@ -1,12 +0,0 @@
-discard """
-  output: "11"
-"""
-
-proc p(x, y: int): int =
-  result = x + y
-
-echo p((proc (): int =
-          var x = 7
-          return x)(),
-       (proc (): int = return 4)())
-
diff --git a/tests/closure/tnoclosure.nim b/tests/closure/tnoclosure.nim
deleted file mode 100644
index 25cce0040..000000000
--- a/tests/closure/tnoclosure.nim
+++ /dev/null
@@ -1,25 +0,0 @@
-discard """
-  output: '''@[1]
-@[1, 1]
-@[1, 2, 1]
-@[1, 3, 3, 1]
-@[1, 4, 6, 4, 1]
-@[1, 5, 10, 10, 5, 1]
-@[1, 6, 15, 20, 15, 6, 1]
-@[1, 7, 21, 35, 35, 21, 7, 1]
-@[1, 8, 28, 56, 70, 56, 28, 8, 1]
-@[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]'''
-"""
-
-import sequtils
-
-proc pascal(n: int) =
-  var row = @[1]
-  for r in 1..n:
-    echo row
-    row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1])
-
-pascal(10)
-
-# bug #3499 last snippet fixed
-# bug 705  last snippet fixed
diff --git a/tests/closure/tstmtlist.nim b/tests/closure/tstmtlist.nim
new file mode 100644
index 000000000..6a1390617
--- /dev/null
+++ b/tests/closure/tstmtlist.nim
@@ -0,0 +1,9 @@
+discard """
+  action: compile
+"""
+
+proc foo(x: proc()) = x()
+foo: echo "a" #[tt.Warning
+     ^ statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead [StmtListLambda]]#
+foo do: echo "b" #[tt.Warning
+        ^ statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead [StmtListLambda]]#
diff --git a/tests/closure/ttimeinfo.nim b/tests/closure/ttimeinfo.nim
index 3138ae72e..24d535cbf 100644
--- a/tests/closure/ttimeinfo.nim
+++ b/tests/closure/ttimeinfo.nim
@@ -1,15 +1,22 @@
+discard """
+output: '''
+@[2000-01-01T00:00:00Z, 2001-01-01T00:00:00Z, 2002-01-01T00:00:00Z, 2003-01-01T00:00:00Z, 2004-01-01T00:00:00Z, 2005-01-01T00:00:00Z, 2006-01-01T00:00:00Z, 2007-01-01T00:00:00Z, 2008-01-01T00:00:00Z, 2009-01-01T00:00:00Z, 2010-01-01T00:00:00Z, 2011-01-01T00:00:00Z, 2012-01-01T00:00:00Z, 2013-01-01T00:00:00Z, 2014-01-01T00:00:00Z, 2015-01-01T00:00:00Z]
+@[2000-01-01T00:00:00Z, 2001-01-01T00:00:00Z, 2002-01-01T00:00:00Z, 2003-01-01T00:00:00Z, 2004-01-01T00:00:00Z, 2005-01-01T00:00:00Z, 2006-01-01T00:00:00Z, 2007-01-01T00:00:00Z, 2008-01-01T00:00:00Z, 2009-01-01T00:00:00Z, 2010-01-01T00:00:00Z, 2011-01-01T00:00:00Z, 2012-01-01T00:00:00Z, 2013-01-01T00:00:00Z, 2014-01-01T00:00:00Z, 2015-01-01T00:00:00Z]
+'''
+"""
+
 # bug #2073
 
 import sequtils
 import times
 
 # 1
-proc f(n: int): TimeInfo =
-  TimeInfo(year: n, month: mJan, monthday: 1)
+proc f(n: int): DateTime =
+  initDateTime(1, mJan, n, 0, 0, 0, utc())
 
 echo toSeq(2000 || 2015).map(f)
 
 # 2
-echo toSeq(2000 || 2015).map(proc (n: int): TimeInfo =
-  TimeInfo(year: n, month: mJan, monthday: 1)
+echo toSeq(2000 || 2015).map(proc (n: int): DateTime =
+  initDateTime(1, mJan, n, 0, 0, 0, utc())
 )