Hi everyone, i am working on tokio application where i need to pass a struct in to the stream fold , that struct contains a closures and/or pointers to the functions (depends). I have tried many different approaches and could not pass compiler errors like live times and so on.
I have created Gist code example of how i would like it to work (it is just and example and i would really like to get rid of Boxes and make it look nicer). Unfortunately it does not work any way (with or without Boxes)
I would really appreciate if someone helps me with this issue and explains why i it should be that way as i have spend last 3 days trying to resolve and could not do that. Thank you very much
Also i had topic on reddit related this issue:
Futures don't execute in the place where they're written. They will execute somewhere else, in the future, long after all your variables, all your function calls, are gone.
await lands, you can't use references anywhere in futures.
move on all closures used in futures.
- Make sure things can actually be moved, i.e. no types with
Arc are fine.
Even if i put
move everywhere i get
cannot move out of captured variable in an 'FnMut' error on stream
fold method. Using only Boxes.
oh, I see it!
You have TWO
FnMut's nested. One in
for_each, and other in
fold. That means the inner closure is not just one closure, it's many closures, each created for every run of
So it means that your one variable is trying to be moved into
fold many times, for each
The solution is two wrap it in
Arc, and then in
let myFns = Arc::clone(&myFns);
so that each copy of
fold's closure can have its own copy of
Thanks for helping, after adding Arc i still can not call any functions which are inside of
myFns variable. I have created another gist with Arc added:
The error is:
37 | (myFns.case1Fn.unwrap())(data);
| ^^^^^^^^^^^^^ cannot move out of an `Arc`
Also i tried adding Mutex still no luck
'cannot move out error' usually means you need as_ref() on Option before unwrapping it. Otherwise the Option tries to destroy itself.
Thank you very much for you help seems like it works alright with as_ref and but now i am getting slightly different error i believe it is related to the Send and Sync traits on future, after calling a closure i am getting error on tokio::spawn that it can not send returned future and i have type mismatch.
Box<Future<Item = String, Error = ()>> + Send + Sync> i am getting just
Box<Future<Item = String, Error = ()>>> type. How do you attach Send and Sync to the boxed future ?
The latest gist:
I really appreciate you help as i have learned quite a few things from your comments. Thanks again
It's more helpful to see which types are
rustup component add cargo-fix and
cargo fix --edition
edition = "2018" to your Cargo toml,
cargo fix --edition-idioms
When you're working with an abstract type like
dyn Trait, you get only what you ask for, and nothing more. Even if actual types you use it with support extra properties like Send/Sync, Rust pretends they don't exist, because you didn't ask for them to be guaranteed.
So to guarantee that every boxed future you could get is Send + Sync, you have to explicitly ask for it:
type Func = Box<dyn Fn(Vec<u8>) -> Box<dyn Future<Item = String, Error = ()> + Send + Sync> + Send + Sync>;
Note that you have two
Box<dyn Trait> there, so you have to ask for Send/Sync for both.
Everything is working alright Thank you very much for your help