Description
When working with move
closures, and especially when spawning new threads, I often find myself having to clone a bunch of state (usually Arc
s, but not always). This is either because I want that state to be shared between many instances of a closure or with the closure and the code below the closure (e.g., Arc
/Rc
), or for mundane reasons like I need to have a String
in each closure, and since thread::spawn
requires 'static
, I need to clone. In futures-based code, this happens a lot with Rc<Self>
where I need to carry self along into futures chained with and_then
. Usually, this results in code like this:
for _ in 0..nthreads {
let foo = Arc::clone(&foo);
let bar = Arc::clone(&bar);
let baz = Arc::clone(&baz);
thread::spawn(move || {
This appears a lot in the wild. Some very quick sampling yields: [1], [2], [3], [4], [5], [6], [7], [8].
Even if you're just spawning a single thread, you often need to use weirdly tweaked variable names. For example, this code:
let foo = Arc::new(...);
thread::spawn(move || {
foo.baz();
});
foo.baz();
must be written as
let foo = Arc::new(...);
let foo_clone = foo.clone();
thread::spawn(move || {
foo_clone.baz();
});
foo.baz();
or if you want to retain the foo
name (which you often do), you need to introduce an extra artificial scope:
let foo = Arc::new(...);
{
let foo = foo.clone();
thread::spawn(move || {
foo.baz();
});
}
foo.baz();
I don't have a concrete proposal for how this would be fixed. It'd be really neat to have something like clone ||
, but that's probably overly simplistic as often you want to move some variables and clone others. Some better ergonomics for this would be great!