This code does not compile without adding move
to the closure. It produces the error:
error[E0373]: closure may outlive the current function, but it borrows `foo`, which is owned by the current function
--> src/main.rs:26:18
|
26 | do_something(|| {
| ^^ may outlive borrowed value `foo`
27 | foo.bar += 1;
| --- `foo` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:26:5
|
26 | / do_something(|| {
27 | | foo.bar += 1;
28 | | println!("{}", foo.bar);
29 | | });
| |______^
help: to force the closure to take ownership of `foo` (and any other referenced variables), use the `move` keyword
|
26 | do_something(move || {
| ^^^^^^^
This error is confusing, as it seems to imply a lifetime longer than 'static is required, as if anything could outlive 'static. Here foo
is a 'static
reference to a struct. If I add move
to the closure, isn't it going to move the referenced struct itself into the closure? Or is it just copying the reference (the pointer bits)? It seems to me that it's just moving the reference, not Foo
itself. My understanding is very fuzzy about how move closures work with respect to references.
struct Foo {
bar: i32,
}
impl Drop for Foo {
fn drop(&mut self) {
panic!("dropping Foo, should never happen");
}
}
pub fn do_something<F, T>(mut f: F)
where
F: FnMut() -> T + 'static,
T: 'static,
{
// "spawn" 3 threads
f();
f();
f();
}
fn main() {
let foo = Box::leak::<'static>(Box::new(Foo { bar: 0 }));
let raw_ptr: *const Foo = foo;
do_something(move || {
foo.bar += 1;
println!("{}", foo.bar);
});
println!("{}", unsafe { (*raw_ptr).bar });
}
This question is similar to Specifying static lifetime of value in `main` so callback can borrow but I don't think it's a duplicate.
'static
here. – trentcl