Hi everyone!
I tried to borrow T
immutably in async block, but the Rust compiler tells me to add Send
trait to T
.
In the following code, test_works1
and test_works2
work fine, but test_not_work1
and test_not_work2
are not. I don’t understand.
Code
use core::future::Future;
use core::pin::Pin;
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;
trait Inner {
fn inner_test<'a>(&'a self) -> BoxFuture<'a, ()>;
}
struct Foo<T: Inner>(T);
impl<T: Inner> Foo<T> {
async fn test(&self) {
self.0.inner_test().await
}
}
// it works
fn test_works1<'a, T: Inner + Sync>(foo_ref: &'a Foo<T>) -> BoxFuture<'a, ()> {
let foo_inner_ref = &foo_ref.0;
Box::pin(async move { foo_inner_ref.inner_test().await })
}
fn test_not_work1<'a, T: Inner + Sync>(foo_ref: &'a Foo<T>) -> BoxFuture<'a, ()> {
Box::pin(async { foo_ref.0.inner_test().await })
}
fn test_not_work2<'a, T: Inner + Sync>(foo_ref: &'a Foo<T>) -> BoxFuture<'a, ()> {
Box::pin(async { foo_ref.test().await })
}
// it works
async fn test_works2<T: Inner + Sync>(foo_ref: &Foo<T>) {
foo_ref.test().await;
}
fn main() {}
Error
error: future cannot be sent between threads safely
--> src/main.rs:25:5
|
25 | Box::pin(async { foo_ref.0.inner_test().await })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
note: future is not `Send` as this value is used across an await
--> src/main.rs:25:22
|
25 | Box::pin(async { foo_ref.0.inner_test().await })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `foo_ref.0` maybe used later...
note: `foo_ref.0` is later dropped here
--> src/main.rs:25:51
|
25 | Box::pin(async { foo_ref.0.inner_test().await })
| --------- ^
| |
| has type `T` which is not `Send`
help: consider moving this into a `let` binding to create a shorter lived borrow
--> src/main.rs:25:22
|
25 | Box::pin(async { foo_ref.0.inner_test().await })
| ^^^^^^^^^^^^^^^^^^^^^^
= note: required for the cast to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
24 | fn test_not_work1<'a, T: Inner + Sync + Send>(foo_ref: &'a Foo<T>) -> BoxFuture<'a, ()> {
| ^^^^^^
error: future cannot be sent between threads safely
--> src/main.rs:29:5
|
29 | Box::pin(async { foo_ref.test().await })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
note: future is not `Send` as this value is used across an await
--> src/main.rs:14:9
|
14 | self.0.inner_test().await
| ^^^^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `self.0` maybe used later...
note: `self.0` is later dropped here
--> src/main.rs:15:5
|
14 | self.0.inner_test().await
| ------ has type `T` which is not `Send`
15 | }
| ^
help: consider moving this into a `let` binding to create a shorter lived borrow
--> src/main.rs:14:9
|
14 | self.0.inner_test().await
| ^^^^^^^^^^^^^^^^^^^
= note: required for the cast to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
28 | fn test_not_work2<'a, T: Inner + Sync + Send>(foo_ref: &'a Foo<T>) -> BoxFuture<'a, ()> {
| ^^^^^^
error: aborting due to 2 previous errors
error: could not compile `playground`