#clone #terrazzo #macro #utility #proc-macro

macro autoclone

A simple macro to clone variables before passing them into a move closure or async block

5 releases

0.1.5 Feb 26, 2025
0.1.4 Feb 24, 2025
0.1.3 Dec 28, 2024
0.1.2 Dec 28, 2024
0.1.1 Dec 27, 2024

#1925 in Procedural macros

Download history 393/week @ 2024-12-25 41/week @ 2025-01-01 8/week @ 2025-01-08 8/week @ 2025-01-15 11/week @ 2025-01-22 7/week @ 2025-01-29 12/week @ 2025-02-05 25/week @ 2025-02-12 125/week @ 2025-02-19 207/week @ 2025-02-26

370 downloads per month
Used in 5 crates (3 directly)

MIT license

15KB
336 lines

A simple macro to clone variables before passing them into a move closure or async block.


lib.rs:

A simple macro to clone variables before passing them into a move closure or async block.

Usage

The list of variables to clone is defined at the beginning of the block, which is easier to add cloning for variables.

With autoclone:

#[autoclone]
fn test() {
    let my_string = "Hello, World!".to_string();
    let callback = move || {
        // Declare variables that need cloning.
        // `autoclone!(<my_variable>, <other_variable>, ...);`
        // Just remove the `autoclone!(...);` statement if cloning is not required.
        autoclone!(my_string);
        println!("Inside the move callback: {my_string}");
    };
    println!("Outside the move callback: {my_string}");
    callback();
}

Comparison with clone-macro

With clone-macro:

fn test() {
    let my_string = "Hello, World!".to_string();
    // Adding cloning is not trivial
    // - requires adding/removing `clone!([my_string]` if cloning is necessary
    // - requires adding/removing the corresponding closing `)`
    let callback = clone!([my_string], move || {
        println!("Inside the move callback: {my_string}");
    });
    println!("Outside the move callback: {my_string}");
    callback();
}

See also https://docs.rs/clone-macro

Syntax sugar

The autoclone!() macro does not exist. Instead, the #[autoclone] proc macro modifies the code. You can see the modified code using #[autoclone(debug = true)]

The previous example expands to

fn test() {
    let my_string = "Hello, World!".to_string();
    let callback = {
        let my_string = my_string.to_owned();
        move || {
            println!("Inside the move callback: {my_string}");
        }
    };
    println!("Outside the move callback: {my_string}");
    callback();
}

Dependencies

~0.8–1.3MB
~29K SLoC