- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
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
  rustc :)
Thanks upfront!
Metadata
Metadata
Assignees
Labels
Type
Projects
Status