Closed Tuetuopay closed 2 years ago
I don't think this has anything to do with async-trait. A future is not Send and the error is bad. The only relevance of async-trait in your code is that's where you get the Send bound.
Here is a smaller repro:
use futures::StreamExt;
fn require_send<T: Send>(_: T) {}
fn main() {
require_send(async {
futures::stream::empty()
.map(std::future::ready::<&()>)
.buffered(1)
.next()
.await;
});
}
error: higher-ranked lifetime error
--> src/main.rs:242:5
|
242 | / require_send(async {
243 | | futures::stream::empty()
244 | | .map(std::future::ready::<&()>)
245 | | .buffered(1)
246 | | .next()
247 | | .await;
248 | | });
| |______^
|
= note: could not prove `impl futures::Future<Output = ()>: std::marker::Send`
Wow thanks for the smaller repro!
Do you have any pointers on how to fix this? And if this is a bug somewhere? I guess the root cause is futures
's futures made from stream don't implement Send
, while I think they should if the enclosed futures do.
Should I raise an issue to futures (for them to be Send) / rustc (to improve the error message)?
I stumbled on some weird borrow checker issue when using streams in code called by a function implementation of an async trait (my use case being Tonic, where the server is defined as such). Interestingly, the issue disappears when relaxing the thread safety requirement of async trait (with
?Send
passed to the proc macro).Here you can find a playground with the faulty code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=77493d971e9227e5dcd6bcf75f286335. I did add a few variations of the faulty code involving streams, end there are a few takeaways:
buffered
streamsThe actual error is pretty cryptic:
Interestingly, the above error is using Rust 1.63 with the new improved error messages. Yay borrow checker! If using 1.62, we get something more verbose that may give more info.
Thanks!