Repository navigation
Tracking issue for async/await (RFC 2394) #50547
Copy link
Copy link
Closed
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-coroutinesArea: CoroutinesArea: CoroutinesAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-langRelevant to the language teamRelevant to the language team
Description
This is the tracking issue for RFC 2394 (rust-lang/rfcs#2394), which adds async and await syntax to the language.
I will be spearheading the implementation work of this RFC, but would appreciate mentorship as I have relatively little experience working in rustc.
TODO:
- Implement
- Stabilize Stabilize
async_awaitin Rust 1.39.0 #63209 - Document
Unresolved questions:
- Final syntax for
await. - Resolution of RFC: add futures and task system to libcore rfcs#2418
- Prevent await from creating a generator #51719
- async/await assertion failed: unbounded recursion #53249
- Missing detection of Send for async fn #53259
- async/await: “the requirement
for<'r> 'r : 'staticis not satisfied” with'staticacross await point #53548 (initially “expected bound lifetime parameter, found concrete lifetime” with'staticacross await point futures-rs#1199) - ICE with --pretty=expanded and async/await #53447
- Double-check
Tryimplementations to which we want to commit
Reacted by Rizky Luthfianto, Yehia Amer, Sai Zeng, EFanZh, Clemens Koza, Elaine, 寧靜, jadon belezos, memoryruins, Anirudh and 289 more
Reacted by Árpád Goretity and Hussein A.
Reacted by Null, hirrolot, clint21.eth ⚡️, Rust, hexrcs, lidongjies, xahon, Mehrdad Khanzadeh, AsyncIter, Songtronix and 2 more
Reacted by Charles Lew, Kevin Wang, cybai, Alexander Regueiro, Matt, Ravi Teja, Psilon, Rizky Luthfianto, Christian Hudon, brotzeit and 146 more
Reacted by Rizky Luthfianto, EFanZh, Elaine, memoryruins, Eyal Kalderon, shekohex, Yuri Bochkarev, Anthony Dodd, Léo Gaspard, Simon Massey and 123 more
Reacted by Null, hirrolot, krinoid, 棒棒大, clint21.eth ⚡️, Miles Granger, Tibin Thomas, Rust, Andrew Jakubowicz, Jack and 22 more
Reacted by mark, Yahor Siarheyenka, Alex Gutan, hirrolot, shekohex, davyzhang, Cyril Tovena, Stephen Blum, Virgiel, Beau Hoyt and 24 more
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-coroutinesArea: CoroutinesArea: CoroutinesAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-langRelevant to the language teamRelevant to the language team
Activity
rpjohnst commentedon May 8, 2018
The discussion here seems to have died down, so linking it here as part of the
awaitsyntax question: https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344withoutboats commentedon May 9, 2018
Implementation is blocked on #50307.
Pzixel commentedon May 10, 2018
About syntax: I'd really like to have
awaitas simple keyword. For example, let's look on a concern from the blog:I agree here, but braces are evil. I think it's easier to remember that
?has lower precedence thanawaitand end with it:let foo = await future?It's easier to read, it's easier to refactor. I do believe it's the better approach.
Allows to better understand an order in which operations are executed, but imo it's less readable.
I do believe that once you get that
await foo?executesawaitfirst then you have no problems with it. It's probably lexically more tied, butawaitis on the left side and?is on the right one. So it's still logical enough toawaitfirst and handleResultafter it.If any disagreement exist, please express them so we can discuss. I don't understanda what's silent downvote stands for. We all wish good to the Rust.
alexreg commentedon May 10, 2018
I have mixed views on
awaitbeing a keyword, @Pzixel. While it certainly has an aesthetic appeal, and is perhaps more consistent, givenasyncis a keyword, "keyword bloat" in any language is a real concern. That said, does havingasyncwithoutawaiteven make any sense, feature wise? If it does, perhaps we can leave it as is. If not, I'd lean towards makingawaita keyword.Nemo157 commentedon May 10, 2018
It might be possible to learn that and internalise it, but there's a strong intuition that things that are touching are more tightly bound than things that are separated by whitespace, so I think it would always read wrong on first glance in practice.
It also doesn't help in all cases, e.g. a function that returns a
Result<impl Future, _>:rpjohnst commentedon May 10, 2018
The concern here is not simply "can you understand the precedence of a single await+
?," but also "what does it look like to chain several awaits." So even if we just picked a precedence, we would still have the problem ofawait (await (await first()?).second()?).third()?.A summary of the options for
awaitsyntax, some from the RFC and the rest from the RFC thread:await { future }?orawait(future)?(this is noisy).await future?or(await future)?does what is expected (both of these feel surprising).await? future(this is unusual).awaitpostfix somehow, as infuture await?orfuture.await?(this is unprecedented).?did, as infuture@?(this is "line noise").@alexreg It does. Kotlin works this way, for example. This is the "implicit await" option.
alexreg commentedon May 10, 2018
@rpjohnst Interesting. Well, I'm generally for leaving
asyncandawaitas explicit features of the language, since I think that's more in the spirit of Rust, but then I'm no expert on asynchronous programming...Pzixel commentedon May 10, 2018
@alexreg async/await is really nice feature, as I work with it on day-to-day basis in C# (which is my primary language). @rpjohnst classified all possibilities very well. I prefer the second option, I agree on others considerations (noisy/unusual/...). I have been working with async/await code for last 5 years or something, it's really important to have such a flag keywords.
@rpjohnst
In my practice you never write two
await's in one line. In very rare cases when you need it you simply rewrite it asthenand don't use await at all. You can see yourself that it's much harder to read thanSo I think it's ok if language discourages to write code in such manner in order to make the primary case simpler and better.
hero awayfuture await?looks interesting although unfamiliar, but I don't see any logical counterarguments against that.rpjohnst commentedon May 10, 2018
But is this because it's a bad idea regardless of the syntax, or just because the existing
awaitsyntax of C# makes it ugly? People made similar arguments aroundtry!()(the precursor to?).The postfix and implicit versions are far less ugly:
Pzixel commentedon May 10, 2018
I think it's a bad idea regardless of the syntax because having one line per
asyncoperation is already complex enough to understand and hard to debug. Having them chained in a single statement seems to be even worse.For example let's take a look on real code (I have taken one piece from my project):
It shows that in practice it doesn't worth to chain
awaits even if syntax allows it, because it would become completely unreadableawaitjust makes oneliner even harder to write and read, but I do believe it's not the only reason why it's bad.Possibility to distinguish task start and task await is really important. For example, I often write code like that (again, a snippet from the project):
Here we are creating N async requests and then awaiting them. We don't await on each loop iteration, but firstly we create array of async requests and then await them all at once.
I don't know Kotlin, so maybe they resolve this somehow. But I don't see how you can express it if "running" and "awaiting" the task is the same.
So I think that implicit version is a no-way in even much more implicit languages like C#.
In Rust with its rules that doesn't even allow you to implicitly convert
u8toi32it would be much more confusing.298 remaining items
MehrdadKhnzd commentedon Jul 8, 2019
Hello there! When we have to expect the stable release of this feature? And how can I use that in nightly builds?
MajorBreakfast commentedon Jul 8, 2019
@MehrdadKhnzd #62149 contains information about the target release date and more
DoumanAsh commentedon Aug 11, 2019
Is there plan to automatically implement
Unpinfor futures that are generated byasync fn?Specifically I'm wondering if Unpin is not available automatically due to generated Future code itself, or whether cuz we can use references as arguments
jkarneges commentedon Aug 17, 2019
@DoumanAsh I suppose if an async fn never has any active self-references at yield points then the generated Future could conceivably implement Unpin, maybe?
jonhoo commentedon Aug 20, 2019
I think that would need to be accompanied by some pretty helpful error messages saying "not
Unpinbecause of this borrow" + a hint of "alternatively you can box this future"Rollup merge of rust-lang#63209 - Centril:stabilize-async-await, r=cr…
bstrie commentedon Sep 23, 2019
The stabilization PR at #63209 notes that "All the blockers are now closed." and was landed into nightly on August 20, therefore heading for the beta cut later this week. It seems worth noting that since August 20 some new blocking issues have been filed (as tracked by the AsyncAwait-Blocking tag). Two of these (#63710, #64130) appear to be nice-to-haves that would not actually impede stabilization, however there are three other issues (#64391, #64433, #64477) which seem worth discussing. These latter three issues are related, all of them arising due to PR #64292, which itself was landed to address AsyncAwait-Blocking issue #63832. A PR, #64584, has already landed in an attempt to address the bulk of the problems, but the three issues remain open for now.
The silver lining is that the three serious open blockers appear to concern code that should compile, but does not currently compile. In that sense, it would be backwards-compatible to land fixes later without impeding the beta-ization and eventual stabilization of async/await. However, I'm wondering whether anyone from the lang team thinks that anything here is concerning enough to suggest that async/await should bake on nightly for another cycle (which, as distasteful as that may sound, is the point of the rapid release schedule after all).
Centril commentedon Sep 23, 2019
@bstrie We are just reusing "AsyncAwait-Blocking" for lack of a better label to note them as "high priority", they are not actually blocking. We should revamp the labeling system soon to make it less confusing, cc @nikomatsakis.
earthengine commentedon Sep 29, 2019
jonhoo commentedon Sep 29, 2019
@earthengine I don't think that's a fair assessment of the situation. The issues that have come up have all been worth taking seriously. It wouldn't be good to land async await only for people to then run into these issues trying to use it in practice :)
Rollup merge of rust-lang#137061 - progressive-galib:gen_future-closi…
Unrolled build for rust-lang#137061
Rollup merge of rust-lang#137061 - progressive-galib:gen_future-closi…
Rollup merge of rust-lang#137061 - progressive-galib:gen_future-closi…