Skip to content

Commit f9efba2

Browse files
committed
results.? compatibity
This PR uses the facilities provided in status-im/nim-stew#134 to support `?` in `async` proc's.
1 parent 2c7774d commit f9efba2

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

chronos.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ license = "MIT or Apache License 2.0"
88
skipDirs = @["tests"]
99

1010
requires "nim >= 1.2.0",
11-
"stew",
11+
"stew#assign-result",
1212
"bearssl",
1313
"httputils",
1414
"unittest2"

chronos/asyncmacro2.nim

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
# distribution, for details about the copyright.
88
#
99

10-
import std/[macros]
10+
import
11+
std/[macros]
1112

1213
proc skipUntilStmtList(node: NimNode): NimNode {.compileTime.} =
1314
# Skips a nest of StmtList's.
@@ -131,6 +132,12 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
131132
cast[`internalFutureType`](`internalFutureSym`)
132133
procBody = prc.body.processBody(castFutureSym, baseTypeIsVoid)
133134

135+
# Support `let x = ? await ...`
136+
assignResultSym = ident "assignResult?"
137+
assignResult = quote do:
138+
template `assignResultSym`(v: Result) =
139+
`castFutureSym`.complete(v)
140+
134141
# don't do anything with forward bodies (empty)
135142
if procBody.kind != nnkEmpty:
136143
# fix #13899, `defer` should not escape its original scope
@@ -143,11 +150,12 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
143150
template result: auto {.used.} =
144151
{.fatal: "You should not reference the `result` variable inside" &
145152
" a void async proc".}
153+
146154
# -> complete(chronosInternalRetFuture)
147155
let complete =
148156
newCall(newIdentNode("complete"), castFutureSym)
149157

150-
newStmtList(resultTemplate, procBodyBlck, complete)
158+
newStmtList(resultTemplate, assignResult, procBodyBlck, complete)
151159
else:
152160
# -> iterator nameIter(chronosInternalRetFuture: Future[T]): FutureBase {.closure.} =
153161
# -> {.push warning[resultshadowed]: off.}
@@ -170,6 +178,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
170178
newNimNode(nnkPragma).add(
171179
newIdentNode("pop")),
172180

181+
assignResult,
182+
173183
procBodyBlck,
174184

175185
# -> complete(chronosInternalRetFuture, result)
@@ -311,5 +321,5 @@ macro async*(prc: untyped): untyped =
311321
result.add asyncSingleProc(oneProc)
312322
else:
313323
result = asyncSingleProc(prc)
314-
when chronosDumpAsync:
324+
when true or chronosDumpAsync:
315325
echo repr result

tests/testmacro.nim

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,20 @@ proc testAwaitne(): Future[bool] {.async.} =
9494

9595
return true
9696

97+
proc resultOk(): Future[Result[int, string]] {.async.} =
98+
return ok(42)
99+
100+
proc resultErr(): Future[Result[int, string]] {.async.} =
101+
return err("string")
102+
103+
proc testResult: Future[Result[int, string]] {.async.} =
104+
let
105+
x = ? await resultOk()
106+
107+
if x == 42:
108+
let _ = ? await resultErr()
109+
return err("not this one")
110+
97111
suite "Macro transformations test suite":
98112
test "`await` command test":
99113
check waitFor(testAwait()) == true
@@ -156,3 +170,18 @@ suite "Closure iterator's exception transformation issues":
156170

157171
waitFor(x())
158172

173+
suite "Result integration":
174+
test "question mark":
175+
# generics are tricky and buggy, test them more!
176+
proc someFunc2[T](v: T): Future[Result[T, string]] {.async.} =
177+
return ok(v)
178+
proc someFunc[T](v: T): Future[Result[T, string]] {.async.} =
179+
let tmp = ? await someFunc2(v)
180+
return ok(tmp + 2)
181+
182+
proc caller(v: int): Future[Result[int, string]] {.async.} =
183+
return ok(3 + ? await someFunc(v))
184+
185+
check waitFor(testResult()).error() == "string"
186+
187+
check waitFor(caller(42))[] == 42 + 2 + 3

0 commit comments

Comments
 (0)