-
Notifications
You must be signed in to change notification settings - Fork 53
Open
Description
Consider the following code:
proc f(): Future[string] {.async.} =
repeat('c', 10)
proc g(): Future[string] {.async.} =
await f()
let x = waitFor g()What practically happens is:
- in the body of
f, a string is allocated and assigned to the returnedFuture await fmakes a copy of that string and assigns it to the future returned bygwaitFor g()makes another copy of the string and assigns it tox
In both cases, the value inside the returned Future is copied because await cannot be sure that it owns the future - that the Future is not used elsewhere.
Lacking knowledge unique ownership at compile time, we have a few options to address this:
- return a
Future[ref string]instead - causes an additional allocation for theref string - make
Future.valuereturn avar Tinstead oflent T- this allowslet x = move(waitFor g()), ie the caller can explicitly choose to move the value out of the future- similarly, we can call the mutable version
mvalueand haveawait/waitForuse the mutable version - ugly because caller has to remember to move, even though 99% of usages don't need it
- similarly, we can call the mutable version
- make
await/waitForinject the move automatically- If the future has multiple references, this will break existing code that expects the
valueto stay in the future - for example:
let f = g() let a = await f let b = await f
- If the future has multiple references, this will break existing code that expects the
- add
mawaitor similarly named alternative that performs the move, leaving the existingawaitas-is- difficult to teach, reasonable only for legacy compat
Metadata
Metadata
Assignees
Labels
No labels