diff --git a/chronos/asyncmacro2.nim b/chronos/asyncmacro2.nim index 429e287..45146a3 100644 --- a/chronos/asyncmacro2.nim +++ b/chronos/asyncmacro2.nim @@ -175,9 +175,25 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = nnkElseExpr.newTree( newStmtList( quote do: {.push warning[resultshadowed]: off.}, - # var result: `baseType` - nnkVarSection.newTree( - nnkIdentDefs.newTree(ident "result", baseType, newEmptyNode())), + # var result {.used.}: `baseType` + # In the proc body, result may or may not end up being used + # depending on how the body is written - with implicit returns / + # expressions in particular, it is likely but not guaranteed that + # it is not used. Ideally, we would avoid emitting it in this + # case to avoid the default initializaiton. {.used.} typically + # works better than {.push.} which has a tendency to leak out of + # scope. + # TODO figure out if there's a way to detect `result` usage in + # the proc body _after_ template exapnsion, and therefore + # avoid creating this variable - one option is to create an + # addtional when branch witha fake `result` and check + # `compiles(procBody)` - this is not without cost though + nnkVarSection.newTree(nnkIdentDefs.newTree( + nnkPragmaExpr.newTree( + ident "result", + nnkPragma.newTree(ident "used")), + baseType, newEmptyNode()) + ), quote do: {.pop.}, ) ) diff --git a/tests/testmacro.nim b/tests/testmacro.nim index 2526c5d..ad4c22f 100644 --- a/tests/testmacro.nim +++ b/tests/testmacro.nim @@ -177,6 +177,10 @@ suite "Macro transformations test suite": of false: await implicit7(v) of true: 42 + proc implicit9(): Future[int] {.async.} = + result = 42 + result + let fin = new int check: waitFor(implicit()) == 42 @@ -193,6 +197,8 @@ suite "Macro transformations test suite": waitFor(implicit8(true)) == 42 waitFor(implicit8(false)) == 33 + waitFor(implicit9()) == 42 + suite "Closure iterator's exception transformation issues": test "Nested defer/finally not called on return": # issue #288