Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implicit return working for async proc #20933

Merged
merged 5 commits into from
Dec 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions lib/pure/asyncmacro.nim
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,18 @@ proc asyncSingleProc(prc: NimNode): NimNode =
# don't do anything with forward bodies (empty)
if procBody.kind != nnkEmpty:
# fix #13899, defer should not escape its original scope
procBody = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody))
procBody.add(createFutureVarCompletions(futureVarIdents, nil))
let blockStmt = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody))
procBody = newStmtList()
let resultIdent = ident"result"
procBody.add quote do:
template setResult(x: `subRetType`) {.used.} =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've considered a similar thing in chronos so that nim-result can work better - status-im/nim-chronos#297 - perhaps we should coordinate the mechanism here - one thing that often comes up is symbol resolution issues - ie template lookup scope is confusing / broken and has a tendency to ruin unrelated code when used together with generics: status-im/nim-stew#161 - as a consequence, we've started using more "unique" names, also for "private" templates like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From reading those PR's I think this is a different problem to whats in them. This doesn't effect how its returned but just means that code like this can now compile and work (Doesn't effect how normal return and result = works)

# Not exactly a good async example, but just needed something basic
proc foo(x: int): Future[string] {.async.} =
  if x mod 2 == 0:
    "even"
  else:
    "odd"

But see what you mean about needing unique names. Maybe could make it very explicit like asyncDispatchSetResult?

# If the proc has implicit return then this will get called
`resultIdent` = x
template setResult(x: untyped) {.used.} =
# If the proc doesn't have implicit return then this will get called
x
procBody.add newCall(ident"setResult", blockStmt)
procBody.add(createFutureVarCompletions(futureVarIdents, nil))
procBody.insert(0): quote do:
{.push warning[resultshadowed]: off.}
when `subRetType` isnot void:
Expand Down
13 changes: 13 additions & 0 deletions tests/async/t11558.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
discard """
output: "Hello\n9"
"""
import std/asyncdispatch

proc foo(): Future[string] {.async.} =
"Hello"

proc bar(): Future[int] {.async.} =
result = 9

echo waitFor foo()
echo waitFor bar()