Repository navigation
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
- StatusShow more project fieldsDone
Activity
compiler-errors commentedon Jul 27, 2023
I'm like 72.5% sure that this is a duplicate of #109924.
GlenDC commentedon Jul 27, 2023
Yes I am sorry. Totally missed that, was looking for it, but couldn't immediately spot it.
You can close this as a duplicate, as I think you're right.
What 's the status on #109924? Is that do-able to fix, or is it a can of worms situation? And can I help to progress this, as this is one of few problems that really is a blocker, as until then I cannot really spawn tasks for each incoming connection? Or is there a work around available?
compiler-errors commentedon Jul 27, 2023
I'm just noting for the record. It's not obvious what the root cause is from the error message, since it kinda sucks.
It's essentially impossible to fix in the old trait solver. It's one of the reasons we are working on the new trait solver -- because we need deferred projection equality (#107507) to solve this problem in general.
You can probably work around this by turbofishing
higher_order_async_fn, e.g.higher_order_async_fn::<EchoService, _>(.....)compiler-errors commentedon Jul 27, 2023
https://godbolt.org/z/9TehW8MvK
GlenDC commentedon Jul 27, 2023
Very cool. I can confirm that this indeed works in my actual code as well. Not ideal, but okay, this does unblock me.
Is there any ETA on when that trait solver would ship in nightly, or is that not for immediate? Just so I manage my own expectations.
compiler-errors commentedon Jul 27, 2023
Not soon is all I can say, unfortunately. It takes a lot of work to rewrite one of the most delicate + fundamental parts of Rust 😃
GlenDC commentedon Jul 27, 2023
Hahaha, got you. That's def. a nasty one. Thanks, appreciate it.
GlenDC commentedon Jul 28, 2023
For now I added the workaround to my FAQ pages, eg https://github.com/plabayo/tower-async#faq
Is there btw somewhere where I can follow progress on the active work regarding the trait resolver rewrite?
compiler-errors commentedon Sep 11, 2023
I'm gonna close this as a dupe of #109924 (edit: wrong issue, sorry), since that's the exact same root cause.
GlenDC commentedon Sep 12, 2023
For a second you got my hopes up, thought it was fixed :')
Seems not, but that's okay, I know this isn't an easy one!
If there's something I can do to help do let me know :)