Async traits
Recipe | Crates | Categories |
---|---|---|
Async traits |
As of Rust 1.75, it is possible to have async
⮳ functions in traits:
struct MyHealthChecker; trait HealthCheck { async fn check(&mut self) -> bool; // <- async fn defined in a Trait } impl HealthCheck for MyHealthChecker { async fn check(&mut self) -> bool { // async fn implementation in the associated impl block do_async_op().await } } async fn do_health_check(mut hc: impl HealthCheck) { if !hc.check().await { // use as normal log_health_check_failure().await; } } async fn do_async_op() -> bool { true } async fn log_health_check_failure() {} #[tokio::main] async fn main() { let hc = MyHealthChecker; do_health_check(hc).await; }
Stabilizing async fn in traits in 2023⮳
This is in turn enabled by return-position impl Trait
in traits, since async fn
is sugar for functions that return -> impl Future
.
// TODO #![allow(dead_code)] trait Container { fn items(&self) -> impl Iterator<Item = u8>; // <-- return Impl in a trait } struct MyContainer { items: Vec<u8>, } impl Container for MyContainer { fn items(&self) -> impl Iterator<Item = u8> { self.items.iter().cloned() } } fn main() { let c = MyContainer { items: vec![1, 2, 3], }; for i in c.items { println!("{}", i); } }
Note that there are still caveats for public traits - see Announcing async fn
and return-position impl Trait
in traits⮳.
In addition, traits that use -> impl Trait
and async fn
are not object-safe, which means they lack support for dynamic dispatch. In the meanwhile, use the async-trait
crate.
use async_trait::async_trait; #[async_trait] trait Advertisement { async fn run(&self); } struct Modal; #[async_trait] impl Advertisement for Modal { async fn run(&self) { self.render_fullscreen().await; for _ in 0..4u16 { remind_user_to_join_mailing_list().await; } self.hide_for_now().await; } } impl Modal { async fn render_fullscreen(&self) {} async fn hide_for_now(&self) {} } async fn remind_user_to_join_mailing_list() {} #[tokio::main] async fn main() { Modal.run().await; }
TODO: review new Rust features
async-trait = Provides a workaround for the lack of language support for async functions in traits