rustasync-awaitclosuresrust-futures

inferred to be a `FnMut` closure


I'm trying to iterate over a vector and add several asynchronous tasks to a Tokyo schedule, but it's throwing the error

inferred to be a FnMut closure

I have tried cloning the data variable, saving it in an ARC and many other things but nothing has worked for me.

I'm starting out in rust and I still don't understand all the concepts well.

for data in settings.data {
        sched.add(
            tokio_cron_scheduler::Job::new_async(
                data.clone().schedule.as_str(),
                move |_, _| Box::pin(async {
                    println!("{}", data.name);
                }),
            ).unwrap()).await.unwrap();
    }
#[derive(Deserialize, Debug)]
pub struct Settings {
    pub data: Vec<Data>
}

#[derive(Deserialize, Debug, Clone)]
pub struct Data {
    pub name: String,
    pub schedule: String
}

This is the error

error: captured variable cannot escape `FnMut` closure body
  --> src\main.rs:30:29
   |
22 |       for data in settings.data {
   |           ---- variable defined here
...
30 |                   move |_, _| Box::pin(async {
   |  ___________________________-_^
   | |                           |
   | |                           inferred to be a `FnMut` closure
31 | |                     log::info!("starting job for task: {}", &data.name);
   | |                                                              ---- variable captured here
32 | |                 }),
   | |__________________^ returns a reference to a captured variable which escapes the closure body
   |
   = note: `FnMut` closures only have access to their captured variables while they are executing...
   = note: ...therefore, they cannot allow references to captured variables to escape

Solution

  • We found a solution that we can use, although it can be done in many other ways, we were trying to use the variable inside the for.

        for data in settings.data {
            let shared_data = std::sync::Arc::new(data);
            sched.add(
                tokio_cron_scheduler::Job::new_async(
                    shared_data.clone().schedule.as_str(),
                     move |_, _| {
                         let data = shared_data.clone();
                         Box::pin(async move {
                             println!("{}", data.name);
                         })
                     },
                ).unwrap()).await.unwrap();
        }