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; } else { println!("Health check was normal"); } } async fn do_async_op() -> bool { true } async fn log_health_check_failure() { println!("Health check failure"); } #[tokio::main] async fn main() { let hc = MyHealthChecker; do_health_check(hc).await; }
[Stabilizing async fn in traits in 2023]blog-stabilizing-async-fn-in-traits⮳.
This is in turn enabled by return-position impl Trait
in traits, since async fn
is sugar for functions that return -> impl Future
.
#[allow(dead_code)] trait Container { // Return `Impl` in a trait fn items(&self) -> impl Iterator<Item = u8>; } 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][p-async] fn
and return-position impl Trait
in traits]blog-announcing-async-fn⮳.
In addition, traits that use -> impl Trait
and [async][p-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) { println!("Render fullscreen"); } async fn hide_for_now(&self) { println!("Hide for now"); } } async fn remind_user_to_join_mailing_list() { println!("Please join our mailing list"); } #[tokio::main] async fn main() { Modal.run().await; }
Related Topics
- Trait Objects.
- Traits.