|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Async-await on stable Rust!" |
| 4 | +author: Niko Matsakis |
| 5 | +--- |
| 6 | + |
| 7 | +**On this coming Thursday, November 7, async-await syntax hits stable |
| 8 | +Rust, as part of the 1.39.0 release.** This work has been a long time |
| 9 | +in development -- the key ideas for zero-cost futures, for example, |
| 10 | +were [first proposed by Aaron Turon and Alex Crichton in |
| 11 | +2016][zcf-rust]! -- and we are very proud of the end result. We believe |
| 12 | +that Async I/O is going to be an increasingly important part of Rust's |
| 13 | +story. |
| 14 | + |
| 15 | +While this first release of "async-await" is a momentous event, it's |
| 16 | +also only the beginning. The current support for async-await marks a |
| 17 | +kind of "Minimum Viable Product" (MVP). We expect to be polishing, |
| 18 | +improving, and extending it for some time. |
| 19 | + |
| 20 | +Already, in the time since [async-await hit beta][aa-beta], we've made |
| 21 | +a lot of great progress, including making some [key diagnostic |
| 22 | +improvements][diag] that help to make async-await errors far more |
| 23 | +approachable. To get involved in that work, check out |
| 24 | +the [Async Foundations Working Group][wg]; if nothing else, you can |
| 25 | +help us by filing bugs about polish issues or by [nominating those |
| 26 | +bugs that are bothering you the most][nom], to help direct our |
| 27 | +efforts. |
| 28 | + |
| 29 | +Many thanks are due to the people who made async-await a reality. The |
| 30 | +implementation and design would never have happened without the |
| 31 | +leadership of cramertj and withoutboats, the implementation and polish |
| 32 | +work from the compiler side (davidtwco, tmandry, gilescope, csmoe), |
| 33 | +the core generator support that futures builds on (Zoxc), the |
| 34 | +foundational work on `Future` and the `Pin` APIs (aturon, |
| 35 | +alexcrichton, RalfJ, pythonesque), and of course the input provided by |
| 36 | +so many community members on RFC threads and discussions. |
| 37 | + |
| 38 | +# Major developments in the async ecosystem |
| 39 | + |
| 40 | +Now that async-await is approaching stabilization, all the major Async |
| 41 | +I/O runtimes are at work adding and extending their support for the |
| 42 | +new syntax: |
| 43 | + |
| 44 | +* the [tokio] runtime [recently announced a number of scheduler |
| 45 | + improvements][tokio-sched], and they are planning a stable release |
| 46 | + in November that supports async-await syntax; |
| 47 | +* the [async-std] runtime [has been putting out weekly releases for the past few months][as-releases], and plans to make their |
| 48 | + 1.0 release shortly after async-await hits stable; |
| 49 | +* using [wasm-bindgen-futures], you can even bridge Rust Futures with |
| 50 | + [JavaScript promises]; |
| 51 | +* the [hyper library][hyper] has [migrated][hyper#1805] to adopt standard Rust futures; |
| 52 | +* the newly released 0.3.0 version of the [futures-rs library][futures] includes support |
| 53 | + for async-await; |
| 54 | +* finally, async-await support is starting to become available in higher-level |
| 55 | + [web frameworks][wf] as well, as well as other interesting applications such |
| 56 | + as the [`futures_intrusive`](https://docs.rs/futures-intrusive/0.2.0/futures_intrusive/) |
| 57 | + crate. |
| 58 | + |
| 59 | +[futures]: https://crates.io/crates/futures-preview |
| 60 | +[tokio]: https://tokio.rs/ |
| 61 | +[zcf-rust]: https://aturon.github.io/blog/2016/08/11/futures/ |
| 62 | +[wasm-bindgen-futures]: https://docs.rs/crate/wasm-bindgen-futures/0.2.16 |
| 63 | +[aa-beta]: https://blog.rust-lang.org/2019/09/30/Async-await-hits-beta.html |
| 64 | +[diag]: https://blog.rust-lang.org/inside-rust/2019/10/11/AsyncAwait-Not-Send-Error-Improvements.html |
| 65 | +[wg]: https://rust-lang.github.io/compiler-team/working-groups/async-await/ |
| 66 | +[nom]: https://rust-lang.github.io/compiler-team/working-groups/async-await/#nominating-issues |
| 67 | +[tokio-sched]: https://tokio.rs/blog/2019-10-scheduler/ |
| 68 | +[as-releases]: https://github.com/async-rs/async-std/releases |
| 69 | +[0.3.0-alpha]: https://rust-lang-nursery.github.io/futures-rs/blog/2018/07/19/futures-0.3.0-alpha.1.html |
| 70 | +[hyper]: https://hyper.rs |
| 71 | +[hyper#1805]: https://github.com/hyperium/hyper/issues/1805 |
| 72 | +[async-std]: https://async.rs/ |
| 73 | +[wf]: https://www.arewewebyet.org/topics/frameworks/ |
| 74 | + |
| 75 | +### Async-await: a quick primer |
| 76 | + |
| 77 | +*(This section and the next are reproduced from the ["Async-await hits |
| 78 | +beta!"][aa-beta] post.)* |
| 79 | + |
| 80 | +So, what is async await? Async-await is a way to write functions that |
| 81 | +can "pause", return control to the runtime, and then pick up from |
| 82 | +where they left off. Typically those pauses are to wait for I/O, but |
| 83 | +there can be any number of uses. |
| 84 | + |
| 85 | +You may be familiar with the async-await from other languages, such as |
| 86 | +JavaScript or C#. Rust's version of the feature is similar, but with a |
| 87 | +few key differences. |
| 88 | + |
| 89 | +To use async-await, you start by writing `async fn` instead of `fn`: |
| 90 | + |
| 91 | +```rust |
| 92 | +async fn first_function() -> u32 { .. } |
| 93 | +``` |
| 94 | + |
| 95 | +Unlike a regular function, calling an `async fn` doesn't have any |
| 96 | +immediate effect. Instead, it returns a `Future`. This is a suspended |
| 97 | +computation that is waiting to be executed. To actually *execute* the |
| 98 | +future, use the `.await` operator: |
| 99 | + |
| 100 | +```rust |
| 101 | +async fn another_function() { |
| 102 | + // Create the future: |
| 103 | + let future = first_function(); |
| 104 | + |
| 105 | + // Await the future, which will execute it (and suspend |
| 106 | + // this function if we encounter a need to wait for I/O): |
| 107 | + let result: u32 = future.await; |
| 108 | + ... |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +This example shows the first difference between Rust and other |
| 113 | +languages: we write `future.await` instead of `await future`. This |
| 114 | +syntax integrates better with Rust's `?` operator for propagating |
| 115 | +errors (which, after all, are very common in I/O). You can simply |
| 116 | +write `future.await?` to await the result of a future and propagate |
| 117 | +errors. It also has the advantage of making method chaining painless. |
| 118 | + |
| 119 | +### Zero-cost futures |
| 120 | + |
| 121 | +The other difference between Rust futures and futures in other |
| 122 | +languages is that they are based on a "poll" model, which makes them |
| 123 | +**zero cost**. In other languages, invoking an async function |
| 124 | +immediately creates a future and schedules it for execution: awaiting |
| 125 | +the future isn't necessary for it to execute. But this implies some |
| 126 | +overhead for each future that is created. |
| 127 | + |
| 128 | +In contrast, in Rust, calling an async function does not do any |
| 129 | +scheduling in and of itself, which means that we can compose a complex |
| 130 | +nest of futures without incurring a per-future cost. As an end-user, |
| 131 | +though, the main thing you'll notice is that **futures feel "lazy"**: |
| 132 | +they don't do anything until you await them. |
| 133 | + |
| 134 | +If you'd like a closer look at how futures work under the hood, take a |
| 135 | +look at [the executor section] of the [async book], or watch the |
| 136 | +[excellent talk][video] that [withoutboats] gave at [Rust LATAM 2019] |
| 137 | +on the topic. |
| 138 | + |
| 139 | +[the executor section]: https://rust-lang.github.io/async-book/02_execution/04_executor.html |
| 140 | +[video]: https://www.youtube.com/watch?v=skos4B5x7qE |
| 141 | +[Rust LATAM 2019]: https://rustlatam.org/ |
| 142 | +[withoutboats]: https://github.com/withoutboats |
| 143 | +[async book]: https://github.com/rust-lang/async-book |
| 144 | + |
| 145 | +### Summary |
| 146 | + |
| 147 | +We believe that having async-await on stable Rust is going to be a key |
| 148 | +enabler for a lot of new and exciting developments in Rust. If you've |
| 149 | +tried Async I/O in Rust in the past and had problems -- particularly |
| 150 | +if you tried the combinator-based futures of the past -- you'll find |
| 151 | +[async-await integrates much better with Rust's borrowing |
| 152 | +system][bc]. Moreover, there are now a number of great runtimes and |
| 153 | +other libraries available in the ecosystem to work with. So get out |
| 154 | +there and build stuff! |
| 155 | + |
| 156 | +[bc]: http://aturon.github.io/tech/2018/04/24/async-borrowing/ |
0 commit comments