How do I make a async function in trait return a future that is Send?

76 Views Asked by At

I have a trait defined like this:

trait MyTrait {
    async fn my_async_fn(arg: SendType) -> Result<Self, Box<dyn Error>>;
}

How do make the future returned by my_async_fn be Send for everything that Implements the trait?

3

There are 3 best solutions below

0
Chayim Friedman On BEST ANSWER

If you will make the trait public the compiler will help you:

warning: use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
 --> src\main.rs:6:5
  |
6 |     async fn my_async_fn(arg: SendType) -> Result<Self, Box<dyn Error>>;
  |     ^^^^^
  |
  = note: you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
  = note: `#[warn(async_fn_in_trait)]` on by default
help: you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change
  |
6 -     async fn my_async_fn(arg: SendType) -> Result<Self, Box<dyn Error>>;
6 +     fn my_async_fn(arg: SendType) -> impl std::future::Future<Output = Result<Self, Box<dyn Error>>> + Send;

So:

fn my_async_fn(
    arg: SendType,
) -> impl std::future::Future<Output = Result<Self, Box<dyn Error>>> + Send;
0
ya7on On

You can use crate async_trait and just return type without Future

#[async_trait::async_trait]
trait MyTrait {
    async fn my_async_fn(arg: SendType) -> Result<Self, Box<dyn Error>>;
}
0
danda On

Since rust 1.75, you can also use the trait_variant crate to have both Send and non Send versions of the trait, eg:

#[trait_variant::make(HttpService: Send)]
pub trait LocalHttpService {
    async fn fetch(&self, url: Url) -> HtmlBody;
}

See the 1.75 announcement.