Nov. 07, 2019 · Niko Matsakis
On this coming Thursday, November 7, async-await syntax hits stable Rust, as part of the 1. 39 .0 release.This work has been a long time in development – the key ideas for zero-cost futures, for example, werefirst proposed by Aaron Turon and Alex Crichton in 2016! – and we are very proud of the end result. We believe that Async I / O is going to be an increasingly important part of Rust’s story.
While this first release of “async-await” is a momentous event, it’s also only the beginning. The current support for async-await marks a kind of “Minimum Viable Product” (MVP). We expect to be polishing, improving, and extending it for some time.
Already, in the time sinceasync-await hit beta, we’ve made a lot of great progress, including making somekey diagnostic improvementsthat help to make async-await errors far more approachable. To get involved in that work, check out theAsync Foundations Working Group; if nothing else, you can help us by filing bugs about polish issues or bynominating those bugs that are bothering you the most, to help direct our efforts.
Many thanks are due to the people who made async-await a reality. The implementation and design would never have happened without the leadership of cramertj and withoutboats, the implementation and polish work from the compiler side (davidtwco, tmandry, gilescope, csmoe), the core generator support that futures builds on (Zoxc), the foundational work onFuture
and the (Pin) ************** (APIs) aturon, alexcrichton, RalfJ, pythonesque), and of course the input provided by so many community members on RFC threads and discussions.
Now that async-await is approaching stabilization, all the major Async I / O runtimes are at work adding and extending their support for the new syntax:
- thetokioruntimerecently announced a number of scheduler improvements, and they are planning a stable release in November that supports async-await syntax;
- theasync-stdruntimehas been putting out weekly releases for the past few months, and plans to make their 1.0 release shortly after async-await hits stable;
- usingwasm-bindgen-futures, you can even bridge Rust Futures with [JavaScript promises];
- thehyper libraryhasmigratedto adopt standard Rust futures;
- the newly released 0.3.0 version of thefutures-rs libraryincludes support for async-await;
- finally, async-await support is starting to become available in higher-levelweb frameworksas well, as well as other interesting applications such as the
futures_intrusive
crate.
Async-await: a quick primer
(This section and the next are reproduced from the“Async-await hits beta! “post.)
So, what is async await? Async-await is a way to write functions that can “pause”, return control to the runtime, and then pick up from where they left off. Typically those pauses are to wait for I / O, but there can be any number of uses.
You may be familiar with the async-await from other languages, such as JavaScript or C #. Rust’s version of the feature is similar, but with a Few Key Differences.
To use async-await, you start by writingasync fn
instead offn
:
async fn first_function () ->u 32 {..}
Unlike a regular function, calling anasync fn
doesn’t have any immediate effect. Instead, it returns aFuture
. This is a suspended computation that is waiting to be executed. To actuallyexecutethe future, use the. await
operator:
async fn another_function () { // Create the future: let future=first_function (); // Await the future, which will execute it (and suspend // this function if we encounter a need to wait for I / O): let result: u 32=future.await; ... }
This example shows the first difference between Rust and other languages: we writefuture.await
instead ofawait future
. This syntax integrates better with Rust’s?
operator for propagating errors (which, after all, are very common in I / O). You can simply writefuture.await?
to await the result of a future and propagate errors. It also has the advantage of making method chaining painless.
Zero-cost futures
The other difference between Rust futures and futures in other languages is that they are based on a “poll” model, which makes them Zero cost. In other languages, invoking an async function immediately creates a future and schedules it for execution: awaiting the future isn’t necessary for it to execute. But this implies some overhead for each future that is created.
In contrast, in Rust, calling an async function does not do any scheduling in and of itself, which means that we can compose a complex nest of futures without incurring a per-future cost. As an end-user, though, the main thing you’ll notice is thatfutures feel “lazy”: they don’t do anything until you await them.
If you’d like a closer look at how futures work under the hood, take a look atthe executor sectionof theasync book, or watch theexcellent talkthatwithoutboatsgave atRust LATAM 2019on the topic.
Summary
We believe that having async-await on stable Rust is going to be a key enabler for a lot of new and exciting developments in Rust. If you’ve tried Async I / O in Rust in the past and had problems – particularly if you tried the combinator-based futures of the past – you’ll findasync-await integrates much better with Rust’s borrowing system. Moreover, there are now a number of great runtimes and other libraries available in the ecosystem to work with. So get out there and build stuff!
GIPHY App Key not set. Please check settings