I have something like this:
use std::sync::Arc;
fn main() {
let arc = Arc::new(42);
move || { arc.clone() };
move || { arc.clone() };
}
I am getting:
error[E0382]: capture of moved value: `arc`
--> src/main.rs:6:19
|
5 | move || { arc.clone() };
| ------- value moved (into closure) here
6 | move || { arc.clone() };
| ^^^ value captured here after move
|
= note: move occurs because `arc` has type `std::sync::Arc<i32>`, which does not implement the `Copy` trait
I understand why I am getting this: the clone
isn't called before arc
is passed to the closure. I can fix this by defining each closure in a function and clone the Arc
before passing it to the closure, but is there another option?
There is no way around it. You should clone the
Arc
before it is used in a closure. The common pattern is to re-bind the clonedArc
to the same name in a nested scope:This is usually done together with
thread::spawn()
:Because this pattern of cloning things before defining a closure is somewhat common, some people have proposed adding something like
clone ||
as an analog tomove ||
. I wouldn't hold out hope for this happening, but a number of comments there point out that macros can solve the case fairly well.Several crates provide some form of this macro:
It's likely that many projects define their own macro to do something similar. For example, the WASM example rust-todomvc defines:
Which can be used as: