You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Imagine a builder type that is not Send. Builders have methods with following signature: fn xxx(&mut self) -> &mut Self. The compiler seems to think that the &mut Self can stay around, even after a method with signature fn finish(self) is called, which clearly consumes the builder variable and invalidates all the mutable references that might live on.
Steps
use std::rc::Rc;// A builder pattern that is not `Send`.structBuilder(Rc<usize>);implBuilder{fnnew() -> Self{Builder(Rc::new(35))}// Builder pattern methods return &mut Selffnbuild_something(&mutself) -> &mutSelf{self}// But the finish method consumes self!fnfinish(self) -> usize{Rc::try_unwrap(self.0).unwrap()}}asyncfnsomething_async(i:usize) -> Result<(),()>{println!("{i}");Ok(())}asyncfnasync_main(){letmut b = Builder::new();
b.build_something();// this method consumes b!let my_int = b.finish();let _ = something_async(my_int).await;// compiler things b might be used here.println!("{my_int}");}fnmain(){
tokio::spawn(async{async_main().await;});}
gives the following compiler error:
Compiling playground v0.0.1 (/playground)
error: future cannot be sent between threads safely
--> src/main.rs:41:5
|
41 | / tokio::spawn(async {
42 | | async_main().await;
43 | | });
| |______^ future created by async block is not `Send`
|
= help: within `{async block@src/main.rs:41:18: 41:23}`, the trait `Send` is not implemented for `Rc<usize>`, which is required by `{async block@src/main.rs:41:18: 41:23}: Send`
note: future is not `Send` as this value is used across an await
--> src/main.rs:33:37
|
28 | let mut b = Builder::new();
| ----- has type `Builder` which is not `Send`
...
33 | let _ = something_async(my_int).await;
| ^^^^^ await occurs here, with `mut b` maybe used later
note: required by a bound in `tokio::spawn`
--> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/task/spawn.rs:168:21
|
166 | pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
| ----- required by a bound in this function
167 | where
168 | F: Future + Send + 'static,
| ^^^^ required by this bound in `spawn`
error: could not compile `playground` (bin "playground") due to 1 previous error
Possible Solution(s)
No response
Notes
No response
Version
Discovered on 1.77.2, but playground (supposedly running latest) has the same problem.
The text was updated successfully, but these errors were encountered:
Problem
I think this playground example sums it up pretty well: (also provided below just in case playground doesn't have good memory)
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d44511c27085218a34240258a2835ff6
The short summary:
Imagine a builder type that is not
Send
. Builders have methods with following signature:fn xxx(&mut self) -> &mut Self
. The compiler seems to think that the&mut Self
can stay around, even after a method with signaturefn finish(self)
is called, which clearly consumes the builder variable and invalidates all the mutable references that might live on.Steps
gives the following compiler error:
Possible Solution(s)
No response
Notes
No response
Version
The text was updated successfully, but these errors were encountered: