lotsoftools

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.