Skip to content

Clone into closures #2407

Closed
Closed
@jonhoo

Description

@jonhoo

When working with move closures, and especially when spawning new threads, I often find myself having to clone a bunch of state (usually Arcs, 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions