Understanding Rust Error E0706: async fn in Traits
Introduction
In Rust, error E0706 appears when using async functions inside traits. This limitation is a result of unresolved implementation issues – particularly concerning the use of 'impl Trait' in traits.
Erroneous Code Example
#![allow(unused)]
fn main() {
trait T {
// Neither case is currently supported.
async fn foo() {}
async fn bar(&self) {}
}
}
async fn Return Comparison
Rust async functions return an 'impl Future', making the following two examples equivalent:
async fn foo() -> User {
unimplemented!()
}
fn foo(&self) -> impl Future<Output = User> + '_' {
unimplemented!()
}
Implementation Issues
To support async functions in traits, a few implementation issues must be addressed. One such issue is supporting 'impl Trait' in traits, as it would require the use of Generic Associated Types:
impl MyDatabase {
async fn get_user(&self) -> User {
unimplemented!()
}
}
impl MyDatabase {
fn get_user(&self) -> impl Future<Output = User> + '_' {
unimplemented!()
}
}
Async-trait Crate and Boxed Futures
While these issues remain unresolved, the async-trait crate allows the use of async fn in traits by desugaring to "boxed futures" (Pin<Box<dyn Future + Send + 'async>>). Note that each function call using this method results in heap allocation, which may be significant for low-level functions that are called millions of times per second.
More Resources
For further information, consider reading the async book for a deeper understanding of asynchronous programming in Rust.