Difference between (|| var) and (move || var.clone())

⚓ Rust    📅 2025-09-09    👤 surdeus    👁️ 8      

surdeus

Warning

This post was published 64 days ago. The information described in this article may have changed.

Why does (move || args.path.clone()) work, but (|| args.path) doesn't in the following code? What's the difference between them?

cargo add bevy

use std::path::PathBuf;

use bevy::prelude::*;

struct Args {
    path: PathBuf,
}

fn main() {
    let args: Args = Args { path: default() };

    App::new()
        .add_plugins(MinimalPlugins)

        /*
        error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
          --> src/main.rs:29:32
           |
        29 |         .add_systems(Startup, (|| args.path).pipe(startup))
           |                               -^^----------- ---- required by a bound introduced by this call
           |                               ||  |
           |                               ||  closure is `FnOnce` because it moves the variable `args.path` out of its environment
           |                               |this closure implements `FnOnce`, not `FnMut`
           |                               the requirement to implement `FnMut` derives from here
           |
           = note: required for `&'a mut {closure@src/main.rs:29:32: 29:34}` to implement `for<'a> FnOnce()`
           = note: required for `{closure@src/main.rs:29:32: 29:34}` to implement `bevy::prelude::SystemParamFunction<fn() -> PathBuf>`
           = note: required for `{closure@src/main.rs:29:32: 29:34}` to implement `bevy::prelude::IntoSystem<(), PathBuf, (IsFunctionSystem, fn() -> PathBuf)>`
         */
        //.add_systems(Startup, (|| args.path).pipe(startup))

        // This works.
        .add_systems(Startup, (move || args.path.clone()).pipe(startup))

        .run();
}

fn startup(In(path): In<PathBuf>) {
    println!("{path:?}");
}

3 posts - 2 participants

Read full topic

🏷️ Rust_feed