summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/asyncmacro.nim16
-rw-r--r--tests/async/tasync_noasync.nim35
2 files changed, 45 insertions, 6 deletions
diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim
index ce538913f..63c8e6e5c 100644
--- a/lib/pure/asyncmacro.nim
+++ b/lib/pure/asyncmacro.nim
@@ -126,9 +126,19 @@ template await*(f: typed): untyped {.used.} =
     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()
+  template yieldFuture = yield FutureBase()
+
+  when compiles(yieldFuture):
+    var internalTmpFuture: FutureBase = f
+    yield internalTmpFuture
+    (cast[typeof(f)](internalTmpFuture)).read()
+  else:
+    macro errorAsync(futureError: Future[T]) =
+      error(
+        "Can only 'await' inside a proc marked as 'async'. Use " &
+        "'waitFor' when calling an 'async' proc in a non-async scope instead",
+        futureError)
+    errorAsync(f)
 
 proc asyncSingleProc(prc: NimNode): NimNode =
   ## This macro transforms a single procedure into a closure iterator.
diff --git a/tests/async/tasync_noasync.nim b/tests/async/tasync_noasync.nim
index 54f4f597f..0927148bf 100644
--- a/tests/async/tasync_noasync.nim
+++ b/tests/async/tasync_noasync.nim
@@ -1,13 +1,42 @@
 discard """
-  errormsg: "'yield' only allowed in an iterator"
-  cmd: "nim c $file"
-  file: "asyncmacro.nim"
+  cmd: "nim check --hints:off --warnings:off $file"
+  action: "reject"
+  nimout: '''
+tasync_noasync.nim(21, 10) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+tasync_noasync.nim(25, 12) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+tasync_noasync.nim(28, 10) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+tasync_noasync.nim(31, 10) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+tasync_noasync.nim(35, 10) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+tasync_noasync.nim(38, 10) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+tasync_noasync.nim(40, 8) Error: Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead
+'''
 """
 import async
 
 proc a {.async.} =
   discard
 
+# Bad await usage
+proc nonAsyncProc =
+  await a()
+
+proc nestedNonAsyncProc {.async.} =
+  proc nested =
+    await a()
+
+iterator customIterator: int =
+  await a()
+
+macro awaitInMacro =
+  await a()
+
+type DummyRef = ref object of RootObj
+method awaitInMethod(_: DummyRef) {.base.} =
+  await a()
+
+proc improperMultisync {.multisync.} =
+  await a()
+
 await a()
 
 # if we overload a fallback handler to get