Async trait function accepting a reference?

Hello, Rustaceans! I'm working with async traits and need to define an async function within a trait that takes a reference parameter. Given the lifetime constraints and the async_trait macro's handling of lifetimes, is there a recommended approach to achieve this? Are there best practices for passing non-'static references to async trait functions, or should I consider alternative strategies to manage lifetimes effectively in async contexts?

MRE

If you are using Rust 1.75—which stabilized async fn in traits—or newer, you could avoid the problematic 'async_trait lifetime by not using the async_trait crate:

pub trait Trait1<T>: Sized {
    async fn from2(value: T) -> Self;
}

fn main() {
    struct MyNumber(u32);

    impl<'a> Trait1<&'a str> for MyNumber {
        async fn from2(value: &'a str) -> Self {
            let num = value.parse::<u32>().unwrap_or(0);
            MyNumber(num)
        }
    }

    let num = MyNumber::from2("42");
    // println!( "Converted: {}", num.0 );
}

Playground.

4 Likes

From the 1.75 release notes @jofas linked, be cautious of the limitations in section "async fn in public traits" where the auto Send bound is not automatically added to return type of the desugared async trait method. The compiler would issue a warning

warning: use of async fn in public traits is discouraged as auto trait bounds cannot be specified

because retroactively adding it would be a breaking API change. In contrast, the async_trait adds the Send bound on the return type by default. If the trait is intended to work in a multithreaded environment, consider explicitly desugaring the async trait method and add a Send bound on the return type.

1 Like