Static async fn in traits

Impact

  • Able to write async fn in traits and impls and use them in statically dispatched contexts
  • Able to easily declare that T: Trait + Send where "every async fn in Trait returns a Send future"

Design notes

Support async fn syntax in traits.

The core idea is that it desugars into impl trait in traits:


#![allow(unused)]
fn main() {
trait SomeTrait {
    async fn foo(&mut self);
}

// becomes:

trait SomeTrait {
    fn foo<(&mut self) -> impl Future<Output = ()> + '_;
}
}

Naturally it should also work in an impl:


#![allow(unused)]
fn main() {
impl SomeTrait for someType {
    async fn foo(&mut self);
}
}

For async functions in traits to be useful, it is important that traits containing async fn be dyn-safe, which introduces a number of challenges that we have to overcome.

Frequently asked questions

Can users easily bound those GATs with Send, maybe even in the trait definition?

  • People are likely to want to say "I want every future produced by this trait to be Send", and right now that is quite tedious.
  • We need a way to do this.
  • This applies equally to other "-> impl Trait in trait" scenarios.

What about "dyn" traits?

  • See the sections on "inline" and "dyn" async fn in traits below!