# Async Rust Vision Doc, 2023 Update, v2.0 This is a (draft) revamp of the async Rust vision doc. The goal is to outline three things * Where do we want to be by Rust 2023 -- greatest level of detail, scheduled down to months * Where do we want to be by Rust 2024 -- key goals for the upcoming Rust edition * Where do we want to be by Rust 2027 -- longer term prospects, a bit hazy The goal is that, when we're done with this process, we know what we know concretely what we are trying to achieve by 2024 and the big steps we'll be taking to get there (some of which have to happen this year). The 2027 goals are more speculative, but we should have agreement on the "overall shape", if not the precise details or path. *This is the second draft. See also the [original draft and comments from the previous deep dive][og].* [og]: https://hackmd.io/UOoD7w7MQ6CvoC66DdX_Rg?edit# ## Tenets These are the criteria and beliefs that we used to form this roadmap. They are ordered such that, if in conflict, we give priority to the first one. **Progress continuously.** People are building foundational layers in async Rust *now*. We need to ship incrementally, building our way to the end goal, but improving stable Rust along the way. This means maintaining a razor-sharp focus, even as we consider how later developments might interact with our current goals. **Be ambitious.** We need to continue supporting the async Rust code that exists today, but we shouldn't be held back by it. The current experience isn't where we want it to be, and we shouldn't be afraid to propose and make ambitious changes, as long as there's a path from here to there. **Enable the ecosystem**. The primary role of the Rust org is to build the interconnections that allow the ecosystem to scale and interoperate. Sometimes standardizing one layer simplifies further development atop it, allowing for a flourishing ecosystem. **Drive consistency.** The async Rust experience right now varies dramatically depending on your domain, and getting started involves a lot of decisions with non-obvious and long-lasting implications. We need to find ways to make async Rust more uniform. See also the [Rustacean design principles][rdp] (Reliability, Performant, Supportive, Productive, Transparent, Versatile, in that order). The Async Rust experience as it stands now arguably puts Versatility above Reliability, Supportiveness, and Productivity through constructs like `select!` and `FuturesUnordered` as well as the lack of portable libraries and idioms that work uniformly across runtimes. [rdp]: https://rustacean-principles.netlify.app/how_rust_empowers.html ## Change in scope We have sharpened the scope of the roadmap to only include language and library features. Tooling and compiler-based improvements are still part of our overall _vision_ for async, but their dependency graphs look very different. We're more confident in our ability to drive this narrower scope of features and deliver them on a given timeline. We think it would also be great to have others step up and drive the other areas. ## Overview ![layer diagram](https://i.imgur.com/2HmLIDe.png) _Also available in [table form](https://github.com/orgs/rust-lang/projects/28/views/1)._ Generally speaking, each item in this diagram depends on the items beneath it. Solid lines are for things we know we want, dashed lines represent stepping stones, and dotted lines are for things we aren't sure about yet. <!-- | | 2023 | 2024 | 2027 (provisional) | | --- | --- | --- | --- | | "Async fn everywhere" | Async fn in traits (AFIT) MVP | Dynamic dispatch for AFIT, async closures | Async drop | | Portability across runtimes | | Basic traits | The high-level roadmap for the next few years is as follows --> ### 2023: Async fn in trait This year we will stabilize the MVP for async fn in trait. This includes: * `async fn` in trait * `-> impl Trait` in trait * Simple `Send` bounds It must be sufficient for 3 representative use cases to publish stable APIs with. Some less-ergonomic workarounds may be required. * Customizable providers in AWS SDK * Tower service traits * Async on embedded with Embassy * *maybe others* The MVP does _not_ include dynamic dispatch or "complex" cases of Send bounds. In order to ship this year, we'll need a stabilization PR to land sometime in early Q3. This means we need to be firming up open questions and driving to consensus now. ### 2024: Async everywhere By the end of next year, async will have an equal standing in Rust's most commonly used abstraction mechanisms. This should make async feel like an integrated part of the language, supercharging _productivity_. First we want to stabilize an `async Iterator` trait, including combinators like `map`. This involves solving real-world problems with async, captures, and generic code, particularly async closures. Next, round out the `async fn` and RPITIT stories by making dynamic dispatch work using `dyn Trait`. This should remove all use cases for the `async-trait` crate. Finally, make it possible to publish portable implementations of protocols using official traits for runtime interop and basic I/O. Representative use cases are `hyper` and `quinn`. This year will be packed, with a lot of exciting possibilties opening up for the ecosystem. If everything goes according to plan this year, we should have most of the second half to work on these features, in addition to the first half of next year. ### 2027: Everything is awesome With many of the ecosystem's most fundamental limitations out of the way, we'd like to shift our focus making async Rust more _reliable_ and _supportive_. We expect reliability improvements to come mainly through new patterns for managing concurrency ("Combinators 2.0" and structured concurrency), along with a mechanism for async destruction. The fundamental work on abstraction mechanisms like async closures will enable this. It will also be a key thing to look forward to as we work on a `Spawn` trait in 2024. We will support async Rust users by making it much easier to get started with a notion of a global executor for use with `async fn main`, a built-in default runtime, and async APIs for files and sockets in the standard library. We will continue making it possible to customize your runtime while using these features. Finally, we will deliver further productivity improvements through await patterns (`for await`). We're also interested in [async] generators and keyword generics, but tend to see those as separate initiatives. These features are far enough in the future that many details may change. We expect them to come more into focus over the next year or two. Around this time next year (end of Q1 2024) we will add a 2025 milestone and pull some of these features into it. ## Alternatives ### Reliability in 2024 After shipping fundamental abstraction features like async closures and dyn Trait, we can shift our focus directly to the reliability question and start publishing our new opinionated patterns for use in the broader ecosystem. That would mean de-prioritizing productivity and interop. In terms of the tenets, this would place ambition and consistency over continuous progress and enabling the ecosystem. It's true that reliability is one of the most _significant_ problems async Rust faces today, compared to synchronous Rust, and it should be given high priority. It's also likely to be one of the tougher problems to crack, given the diversity of use cases and the many challenges of language design involved. And given its dependence on async closures, there might not be enough iteration time to ship both of these in the same year. On the other hand, we think we have a pretty good handle on what it would take to ship basic I/O traits. Spawn and timer traits require taking an opinionated stance, but only in a pretty narrow sense of whether we can express a structured concurrency paradigm using them, and that doesn't seem too hard to accommodate. Finally, `async Iterator` is a clear goal that requires us to exercise our generic programming muscles and may also itself be useful in building them. There's a chance some of this experimentaion will happen anyway in the meantime. We should do what we can to encourage experimentation with crates like [`futures_concurrency`](https://docs.rs/futures-concurrency/latest/futures_concurrency/). One of the ways we'll do that, of course, is by shipping core abstraction mechanisms. We should then revisit this question when planning for 2025. ### Generators in 2024 There's been some recent debate over whether `async fn next` is the right core primitive for async iteration, rather than `poll_next`. It would be easier to write an async `next` implementation, but the fact that async functions must return a separate object leads to irregularities in how the async version of the trait would work: * You can't store a type implementing `async Iterator` and the future returned by `next()` in the same struct, because one borrows from the other. * `dyn async Iterator` always requires boxing or an equivalent adapter. If we did adopt `poll_next` we would almost certainly want to prioritize generators and async generators, so these could easily be written. This does have a lot of benefits and reduces the need for combinators. Alternatively, we could come up an easy way to still write a `next()`-like implementation as an async function. But it's debated whether this would actually make user's lives much easier, since you are still having to write a state machine by hand. If we did prioritize async generators, we would have to pick something to deprioritize. Maybe portable protocols, since that's less "fundamental" and we want to keep `dyn` to finally finish AFIT. Or maybe we bump `dyn`, because it becomes less important in a world where `async Iterator` is already dyn-safe. ## Tactical planning ![Timeline view](https://i.imgur.com/5lqLkiq.png) _source: [Github project](https://github.com/orgs/rust-lang/projects/28/views/2)_ * By Apr 1: Prepare write-ups for Send bounds * Min RTN (Niko will champion) * Min trait transformers (Anyone want to champion?) * Noncommittal deriver? * By end of Apr: * accepted RFC for one of these three approaches * plus implemented * May * ... * June * ... * By July: * stabilized ## Questions for the group * What do we need to do before we have stabilized? * What should each write-up look like? * Can we include a common piece of code, so we can readily compare? e.g., show how the AWS SDK looks? * What do we need to be doing NOW to reach 2024 goals? 2027 goals? ## Discussion