Bring the Async Rust experience closer to parity with sync Rust

Metadata
Owner(s)Tyler Mandry
Teamslang, libs, libs-api, types
StatusProposed

Summary

Over the next six months, we will continue bringing Async Rust up to par with "sync Rust" by doing the following:

  • Telling a complete story for the use of async fn in traits, unblocking wide ecosystem adoption,
  • Improving the ergonomics of Pin, which is frequently used in low-level async code, and
  • Preparing to support asynchronous (and synchronous) generators in the language.

Motivation

This goal represents the next step on a multi-year program aiming to raise the experience of authoring "async Rust" to the same level of quality as "sync Rust". Async Rust is a crucial growth area, with 52% of the respondents in the 2023 Rust survey indicating that they use Rust to build server-side or backend applications.

The status quo

Async Rust is the most common Rust application area according to our 2023 Rust survey. Rust is a great fit for networked systems, especially in the extremes:

  • Rust scales up. Async Rust reduces cost for large dataplanes because a single server can serve high load without significantly increasing tail latency.
  • Rust scales down. Async Rust can be run without requiring a garbage collector or even an operating system, making it a great fit for embedded systems.
  • Rust is reliable. Networked services run 24/7, so Rust's "if it compiles, it works" mantra means fewer unexpected failures and, in turn, fewer pages in the middle of the night.

Despite async Rust's popularity, using async I/O makes Rust significantly harder to use. As one Rust user memorably put it, "Async Rust is Rust on hard mode." Several years back the async working group collected a number of "status quo" stories as part of authoring an async vision doc. These stories reveal a number of characteristic challenges:

The next 6 months

Tell a complete story for async fn in traits

  • Unblock AFIT in public traits by stabilizing RTN and implementable trait aliases (unblock tower 1.0)
  • Ship 1.0 of the dynosaur crate, enabling dynamic dispatch with AFIT
  • Stretch goal: Implement experimental support for async fn in dyn Trait in nightly

Improve ergonomics around Pin

  • Ratify and implement an RFC for auto-reborrowing of pinned references
  • Stretch goal: Ratify an RFC for safe pin projection

Work toward asynchronous generators

  • Ratify an RFC for synchronous generators
  • Review 1-2 RFCs for asynchronous iteration trait with the lang and libs-api teams and decide on the core trait to be stabilized
  • Stretch goal: Ratify an RFC for unsafe binders and RTN in type position

The "shiny future" we are working towards

Writing async code in Rust should feel just as expressive, reliable, and productive as writing sync code in Rust. Our eventual goal is to provide Rust users building on async with

  • the same core language capabilities as sync Rust (async traits with dyn dispatch, async closures, async drop, etc);
  • reliable and standardized abstractions for async control flow (streams of data, error recovery, concurrent execution), free of accidental complexity;
  • an easy "getting started" experience that builds on a rich ecosystem;
  • good performance by default, peak performance with tuning;
  • the ability to easily adopt custom runtimes when needed for particular environments, language interop, or specific business needs.

Design axioms

  • Uphold sync Rust's bar for reliability. Sync Rust famously delivers on the general feeling of "if it compiles, it works" -- async Rust should do the same.
  • Lay the foundations for a thriving ecosystem. The role of the Rust org is to develop the rudiments that support an interoperable and thriving async crates.io ecosystem.
  • When in doubt, zero-cost is our compass. Many of Rust's biggest users are choosing it because they know it can deliver the same performance (or better) than C. If we adopt abstractions that add overhead, we are compromising that core strength. As we build out our designs, we ensure that they don't introduce an "abstraction tax" for using them.
  • From embedded to GUI to the cloud. Async Rust covers a wide variety of use cases and we aim to make designs that can span those differing constraints with ease.
  • Consistent, incremental progress. People are building async Rust systems today -- we need to ship incremental improvements while also steering towards the overall outcome we want.

Ownership and team asks

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The overall owner of the effort is Tyler Mandry. We have identified owners for subitems below; these may change over time.

SubgoalOwner(s) or team(s)Notes
Overall program managementTyler Mandry
↳ AFIT story blog postTyler Mandry
Return type notationNiko Matsakis
Initial implementationMichael GouletComplete
Author RFCNiko MatsakisComplete
RFC decisionTeam langComplete
↳ Finished implementationMichael Goulet
↳ ReviewsTeam types compiler
↳ Stabilization decisionTeam lang
Implementable trait aliasesTyler Mandry
↳ Author RFCTyler Mandry
↳ ImplementationMichael Goulet
↳ ReviewsTeam types compiler
↳ RFC decisionTeam lang types
Pin reborrowingEric Holk
↳ ImplementationEric Holk
↳ Author RFCEric Holk
↳ RFC decisionTeam lang
Trait for generators (sync)
↳ ImplementationEric Holk
↳ Author RFC
↳ RFC decisionTeam libs-api lang
↳ Design meetingTeam lang2 meetings expected
Trait for async iteration
↳ Author RFC
↳ RFC decisionTeam libs-api lang
↳ Design meetingTeam lang2 meetings expected
↳ Implementation
Dynosaur 1.0Santiago Pastorino
↳ ImplementationSantiago Pastorino
↳ Standard reviewsTyler Mandry

TODO: Stretch goals

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is "tangentially" involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they're expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a 'larger than average' change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Why work on synchronous generators if your goal is to support async?

There are three features we want that all interact quite heavily with each other:

  • Sync generators
  • Async generators
  • Async iteration trait

Of the three, we think we are the closest to ratifying an RFC for synchronous generators. This should help clarify one of the major outstanding questions for the other two items; namely, the relation to pinning. With that out of the way, we should better be able to focus on the iteration trait and how well it works with async generators.

Focusing on pinning first also synergizes well with the efforts to improve the ergonomics of pinning.