Skip to content

async fn trait's method's future does not implement Send trait bound #114142

Closed
@GlenDC

Description

@GlenDC

I tried this code:

#![feature(async_fn_in_trait)]
#![feature(return_type_notation)]

trait Service<Request> {
    type Output;
    type Error;

    async fn call(&mut self, req: Request) -> Result<Self::Output, Self::Error>;
}

struct EchoService;

impl<Request> Service<Request> for EchoService {
    type Output = Request;
    type Error = std::convert::Infallible;

    async fn call(&mut self, req: Request) -> Result<Self::Output, Self::Error> {
        Ok(req)
    }
}

async fn higher_order_async_fn<S, Request>(mut svc: S, req: Request)
where
    S: Service<Request, call(): Send> + Send + 'static,
    S::Output: std::fmt::Debug + Send + 'static,
    S::Error: std::fmt::Debug + Send + 'static,
    Request: Send + 'static,
{
    tokio::spawn(async move {
        let output = svc.call(req).await.unwrap();
        println!("{:?}", output);
    })
    .await
    .unwrap();
}

#[tokio::main]
async fn main() {
    higher_order_async_fn(EchoService, "Hello, World!").await;
}

Playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=b8b7d938b1f7ab5cfe4284e0cc6ab09c

I expected to see this happen: it should work and print "Hello, World!" to the stdout.

Instead, this happened: I get a compile error:

error[[E0277]](https://doc.rust-lang.org/nightly/error_codes/E0277.html): `impl Future<Output = Result<<_ as Service<_>>::Output, <_ as Service<_>>::Error>>` cannot be sent between threads safely
  --> src/main.rs:39:27
   |
39 |     higher_order_async_fn(EchoService, "Hello, World!").await;
   |     --------------------- ^^^^^^^^^^^ `impl Future<Output = Result<<_ as Service<_>>::Output, <_ as Service<_>>::Error>>` cannot be sent between threads safely
   |     |
   |     required by a bound introduced by this call
   |
   = help: the trait `for<'a> Send` is not implemented for `impl Future<Output = Result<<_ as Service<_>>::Output, <_ as Service<_>>::Error>>`
note: required by a bound in `higher_order_async_fn`
  --> src/main.rs:24:33
   |
22 | async fn higher_order_async_fn<S, Request>(mut svc: S, req: Request)
   |          --------------------- required by a bound in this function
23 | where
24 |     S: Service<Request, call(): Send> + Send + 'static,
   |                                 ^^^^ required by this bound in `higher_order_async_fn`

For more information about this error, try `rustc --explain E0277`.

and E0277 refers to:

rustc --explain E0277
You tried to use a type which doesn't implement some trait in a place which expected that trait.

which is not really more helpful then the error msg itself.

Meta

Playground:

Nightly channel
Build using the Nightly version: 1.73.0-nightly

(2023-07-26 0d95f9132909ae7c5f24)

Local version:

rustc --version --verbose:

rustc --version --verbose
rustc 1.72.0-nightly (cb80ff132 2023-07-07)
binary: rustc
commit-hash: cb80ff132a0e9aa71529b701427e4e6c243b58df
commit-date: 2023-07-07
host: aarch64-apple-darwin
release: 1.72.0-nightly
LLVM version: 16.0.5

Background

I also track this issue in plabayo/tower-async#9, an issue in the tower-async repo, which is a monorepo of a fork of the https://github.com/tower-rs/tower and https://github.com/tower-rs/tower-http libraries that I made and maintain, making use of the new upcoming async support as advertised in https://blog.rust-lang.org/inside-rust/2023/05/03/stabilizing-async-fn-in-trait.html, which got me very excited and very invested in starting to prepare for that future.

tower-async is then used by me in another project of mine, https://github.com/plabayo/rama, which is a going to be a general proxy framework with data extraction in mind.

Problem is however that it seems that the futures produced by the tower-async Service does not implement Send. And without my higher order functions requiring themethod(): Send trait bound it won't compile either.

So:

  • in worst case this is a bug in the current incomplete async-fn trait support
  • or in best case it is me missing something obvious, or in other words not knowing how to use this properly. In which case I guess the error message could never the less still use some work as a solution is not immediately clear to me.

Similar to the other F-async_fn_in_trait Static async fn in traits issues I am more then willing to help out where you can make use of me, as I am invested in making this work and thus also be able to run one day this kind of code back in the safer Rust lands of stable rustc :)

Thanks upfront!

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-async_fn_in_traitStatic async fn in traitsT-typesRelevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions