Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inside Rust: Async Working Group July update #1112

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions posts/inside-rust/2023-06-13-Async-WG-June-Update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
layout: post
title: "Async Working Group June update"
author: Niko Matsakis and Tyler Mandry
team: The Rust Async Working Group <https://www.rust-lang.org/governance/wgs/wg-async>
---

This is the June update from the Async Working Group of the Rust Programming Language. In May, we [laid out our plans for the year][may]. Over the last month, we have gotten a clearer picture of the stabilization strategy. The current plan is to stabilize the full async function in trait MVP in two phases:

[may]: https://blog.rust-lang.org/inside-rust/2023/05/03/stabilizing-async-fn-in-trait.html

* Phase 1: support `async fn` and `-> impl Trait` in traits and impls (target: Rust 1.73, Oct 5).
* Phase 2: support "send bounds", likely (but not necessarily) through ["return type notation"][rtn] (target: Rust 1.74, Nov 16).

[rtn]: https://blog.rust-lang.org/inside-rust/2023/05/03/stabilizing-async-fn-in-trait.html#mvp-part-2-send-bounds-and-associated-return-types

The first phase covers the ability to write `async fn` and `-> impl Trait` in both traits and impls, roughly as described in [RFC 3185] and [RFC 3425]. These features have been implemented for some time and they are not controversial, though we are still working to do a final triage of bugs and blockers. This first phase provides functionality roughly equivalent to the existing `#[async_trait]` macro and, as such, it's enough for a great many use cases.

[RFC 3185]: https://rust-lang.github.io/rfcs/3185-static-async-fn-in-trait.html
[RFC 3425]: https://github.com/rust-lang/rfcs/pull/3425

The second phase will add support for the ability to put bounds on the futures returned by async functions. Our case studies found that this was a common need as well, particularly for traits which would appear in the standard library, as such traits do not want to return futures to always be `Send`. We have an experimental implementation of ["return type notation"][rtn] on master, but the best solution for the sends bound problem is still under some debate.

## When to stabilize async functions in traits

One of the key questions we were considering was whether to hold off on stabilizing async functions in traits until we were ready to stabilize a solution for the "send bounds" problem as well. On the one hand, our [case studies][cs] showed that send bounds would be important to many users. Moreover, the stabilization of async functions in traits is going to be a big deal and many users will try using them. We don't want them to get frustrated with missing functionality.

[cs]: https://github.com/rust-lang/async-fundamentals-initiative/tree/master/evaluation/case-studies

On the other hand, a true "send bounds" solution is only needed when you wish to have a trait that *may* or *may not* return `Send` futures. Many users can get by with traits that either *always* require `Send` or *never* require `Send`, as demonstrated by the `#[async_trait]` macro.

Rust has a tradition of making new functionality available incrementally rather than waiting for perfection, and it's always served us well (async functions themselves are an example of this, as is `-> impl Trait` in other functions). Moreover, while it is possible to emulate `async fn` using `-> impl Future`, the translation can be subtle. We feared that releasing `-> impl Trait` support without `async fn` would lead to people misusing the former to emulate the latter. On balance, we felt that it would be better to release async functions as quickly as possible.

## What Phase 1 enables: using Async Functions in Traits

Phase 1 provides enough functionality to make it possible to write traits that contain async functions that are either *always* `Send` or *never* `Send`. This makes it roughly equivalent to what you can do with the `#[async_trait]` macro, but potentially more efficient, since you can avoid boxing when using static dispatch. It is also possible to fill in support for `dyn` dispatch using a macro. We expect that many async trait users in these early phases will wind up using some sort of macros to remove some boilerplate, and are discussing shipping a rust-lang crate that provides these common utilities.

For example, consider the `HealthCheck` trait shown here:

```rust
trait HealthCheck {
async fn check(&mut self);
}

impl HealthCheck for MyType {
async fn check(&mut self) { /* ... */ }
}
```

As written, this `HealthCheck` trait is not guaranteed to return `Send` futures. Using explicit `-> impl Future` notation, however, it is possible to make a variant of the trait that *does* guarantee returning `Send` futures; better yet, it's still possible to write `async fn` in the impl:

```rust
trait SendHealthCheck {
fn check(&mut self) -> impl Future<Output = ()> + Send + '_;
}

impl SendHealthCheck for MyType {
async fn check(&mut self) { /* ... */ }
}
```

If the async fn is not `Send`, the [compiler would error](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=0948f287cd7fae0c8ddad3a586b698f4).

## What Phase 2 enables: the "send bound" problem

Phase 1 is great, but it doesn't support writing traits that only *sometimes* require `Send` bounds. This is really needed for traits that will be used in highly generic contexts, like the standard library. To support those kinds of cases, we really want a solution to the "send bounds" problem. We currently have an experimental implementation of one proposal, return type notation, and this month a draft RFC was [posted to Zulip](https://rust-lang.zulipchat.com/#narrow/stream/187312-wg-async/topic/associated.20return.20types.20draft.20RFC/near/356796689) and then reviewed in a [lang team design meeting](https://github.com/rust-lang/lang-team/blob/master/design-meeting-minutes/2023-05-24-return-type-notation.md). That conversation turned up a few other ideas that hadn't been considered yet, and we are talking about them before settling on a final direction. The goal is to open an RFC for the final approach, whatever that winds up being, later this month.

## Timeline and Roadmap

To provide an overview of our progress and the expected timeline, here is our updated roadmap for stabilizing RPITIT, async functions in traits, and addressing the "send bounds" problem:
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved

- [x] MVP implementation
- [x] Case study evaluations complete
- [x] Accepted RFC for RPITIT (target: 2023-05-31)
- [ ] Evaluation period and bug fixing (target: 2023-06-30)
- [ ] Stabilization report for AFIT authored (target: 2023-07-01)
- [ ] Authored RFC for RTN (target: 2023-07-01)
- [ ] Stabilization complete for 1.73.0 (target: 2023-07-21)
- [ ] Accepted RFC for RTN (target: 2023-08-01)
- [ ] Stabilization report for RTN authored (target: 2023-08-29)
- [ ] Stabilization complete for RTN in 1.74.0 (target: 2023-09-26)

We are working diligently to meet these targets and ensure a smooth and successful stabilization process.

## Conclusion

The Async Working Group is focused on stabilizing RPITIT and async functions in traits together for the Rust 1.73.0 release. We encourage you to test these features, provide feedback, and report any issues you encounter. The "send bounds" problem is also being actively discussed, and we expect to propose a solution soon. Thank you for your support and contributions as we strive to shape the future of asynchronous programming in Rust.

Stay tuned for further updates from the Async Working Group as we progress towards the Rust 1.73.0 release. Together, let's make Rust an even better language for async programming!