Skip to content

Commit

Permalink
fixes #15804 (#15820)
Browse files Browse the repository at this point in the history
* fixes #15804

* fix the existing test

* add the testcase for #15804

Co-authored-by: narimiran <[email protected]>
  • Loading branch information
Araq and narimiran authored Nov 2, 2020
1 parent eb42998 commit dfd8a83
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 15 deletions.
21 changes: 9 additions & 12 deletions lib/pure/asyncmacro.nim
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ proc verifyReturnType(typeName: string, node: NimNode = nil) {.compileTime.} =
error("Expected return type of 'Future' got '$1'" %
typeName, node)

template await*(f: typed): untyped {.used.} =
static:
error "await expects Future[T], got " & $typeof(f)

template await*[T](f: Future[T]): auto {.used.} =
var internalTmpFuture: FutureBase = f
yield internalTmpFuture
(cast[typeof(f)](internalTmpFuture)).read()

proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
## This macro transforms a single procedure into a closure iterator.
## The ``async`` macro supports a stmtList holding multiple async procedures.
Expand Down Expand Up @@ -262,20 +271,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
result.params[0] = parseExpr("owned(Future[void])")

# based on the yglukhov's patch to chronos: https://github.com/status-im/nim-chronos/pull/47
# however here the overloads are placed inside each expanded async
var awaitDefinition = quote:
template await(f: typed): untyped {.used.} =
static:
error "await expects Future[T], got " & $typeof(f)

template await[T](f: Future[T]): auto {.used.} =
var internalTmpFuture: FutureBase = f
yield internalTmpFuture
(cast[type(f)](internalTmpFuture)).read()

if procBody.kind != nnkEmpty:
body2.add quote do:
`awaitDefinition`
`outerProcBody`
result.body = body2

Expand Down
15 changes: 15 additions & 0 deletions tests/async/t15804.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import asyncdispatch

type
Foo*[E] = ref object
op: proc(): Future[bool] {.gcsafe.}

proc newFoo*[E](): Foo[E] =
result = Foo[E]()
result.op = proc(): Future[bool] {.gcsafe,async.} =
await sleepAsync(100)
result = false

when isMainModule:
let f = newFoo[int]()
echo waitFor f.op()
6 changes: 3 additions & 3 deletions tests/async/tasync_noasync.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
discard """
errormsg: "undeclared identifier: 'await'"
errormsg: "'yield' only allowed in an iterator"
cmd: "nim c $file"
file: "tasync_noasync.nim"
file: "asyncmacro.nim"
"""
import async

Expand All @@ -12,4 +12,4 @@ await a()

# if we overload a fallback handler to get
# await only available within {.async.}
# we would need `{.dirty.}` templates for await
# we would need `{.dirty.}` templates for await

0 comments on commit dfd8a83

Please sign in to comment.