Why is a variable not borrowed for static if it is dropped at the end of the main function in Rust?

100 Views Asked by At

I am trying to pass a closure which captures a local variable:

fn main() {

  /* snip */

  let COINT = some_function_call();

  /* snip */

  hermes.with_task(
    u32::MAX,
    1,
    1,
    Box::new(
      |hermes| {
        let mut rng = rand::thread_rng();
        Command::SpawnCommand(
          COIN, 
          Vec3::new(
            rng.gen_range(-WORLD_SIZE..WORLD_SIZE),
            5.5,
            rng.gen_range(-WORLD_SIZE..WORLD_SIZE)
          )
        )
      }
    )
  );

  /* snip */

}

It is the variable COIN.

The error I receive is as follows: 
error[E0597]: `COIN` does not live long enough
   --> src\main.rs:250:11
    |
246 | /     Box::new(
247 | |       |hermes| {
    | |       -------- value captured here
248 | |         let mut rng = rand::thread_rng();
249 | |         Command::SpawnCommand(
250 | |           COIN,
    | |           ^^^^ borrowed value does not live long enough
...   |
257 | |       }
258 | |     )
    | |_____- cast requires that `COIN` is borrowed for `'static`
...
272 |   }
    |   - `COIN` dropped here while still borrowed

The method with_task is defined as follows:

impl Hermes {

  /* snip */
  
  pub fn with_task<'a: 'static>(&mut self, repeat: u32, span: u32, offset: u32, f: Box<dyn Fn(&Hermes) -> Command + 'a>) -> usize {

    let t = TaskInfo {
      task: f,
      repeat,
      span,
      counter: offset,
    };

    self.tasks.push(t);

    self.tasks.len() - 1
  }

  /* snip */

}

What puzzles me most is this line in the error:

272 |   }
    |   - `COIN` dropped here while still borrowed

This is precisely the place where the main function ends, I just do not understand what the problem is.

Thanks for helping me :)

Edit Here is a reproducible example:

struct Foo {
    tasks: Vec<Box<dyn Fn(&Foo) -> Command>>,
}
impl Foo {
    fn with_task(&mut self, f: Box<dyn Fn(&Foo) -> Command>) {
        self.tasks.push(f);
    }
}

enum Command {
    Com1(usize),
}


fn main() {

    let VAR: usize = 0;
    let mut foo = Foo {
        tasks: Vec::new(),
    };

    foo.with_task(Box::new(
        |foo| {
            Command::Com1(VAR)
        }
    ));

}
0

There are 0 best solutions below