fn get_closeures<'a>(x: &'a i64) -> Vec<Box<dyn Fn() + 'a>> {
let mut ret: Vec<Box<dyn Fn() -> ()>> = Vec::new();
ret.push(Box::new(|| println!("{}", x + 1)));
ret.push(Box::new(|| println!("{}", x + 2)));
ret
}
fn main() {
let x: i64 = 100;
{
let closures = get_closeures(&x);
for closure in closures {
closure();
}
}
}
lead to the errors
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
--> src/main.rs:3:23
|
3 | ret.push(Box::new(|| println!("{}", x + 1)));
| ^^ - `x` is borrowed here
| |
| may outlive borrowed value `x`
|
note: closure is returned here
--> src/main.rs:6:5
|
6 | ret
| ^^^
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
3 | ret.push(Box::new(move || println!("{}", x + 1)));
| ++++
My question is that I have mark the lifetime of the argument x
stored must be longer than the closures stored into vector. Why does compiler stop me to borrow x?
I know that I can just add move
keyword on the closure to fix it. But If x is not a i64 but a non Copy struct, then this method should not work.
Also, I think there is no memory problem inside my code, how to convince the rust compiler to believe it?
Note that x
is not of type i64
, but instead of type &i64
, i.e. reference to i64
. So x
will always be Copy
even if the underlying type isn't. Example:
fn get_closeures<'a>(x: &'a str) -> Vec<Box<dyn Fn() + 'a>> {
let mut ret: Vec<Box<dyn Fn() -> ()>> = Vec::new();
ret.push(Box::new(move || println!("{}", x)));
ret.push(Box::new(move || println!("{}", x)));
ret
}
fn main() {
let x: String = "azerty".to_string();
{
let closures = get_closeures(&x);
for closure in closures {
closure();
}
}
}