Closure can't capture a varible if passed to a struct

Hello, I'm learning about closures but I have run in to a little bit of a problem with them. When I just store one in a variable as shown below everything works perfectly, however when I want to store it in the struct I'm receive the following error. Can anyone help me digest this error, because it isn't intuitive for me.

1. Open in split
---
error[E0597]: `a` does not live long enough
  --> src/main.rs:14:31
   |
6  |       let a = 1;
   |           - binding `a` declared here
...
13 |           callback: Box::new(|| {
   |                     -        -- value captured here
   |  ___________________|
   | |
14 | |             println!("{:#?}", a);
   | |                               ^ borrowed value does not live long enough
15 | |         }),
   | |__________- cast requires that `a` is borrowed for `'static`
16 |       };
17 |   }
   |   - `a` dropped here while still borrowed
   |
   = note: due to object lifetime defaults, `Box<dyn Fn()>` actually means `Box<(dyn Fn() + 'static)>`

Code:

struct C {
    callback: Box<dyn Fn()>,
}

fn main() {
    let a = 1;

    let _var = Box::new(|| {
        println!("{:#?}", a);
    });

    let _struct = C {
        callback: Box::new(|| {
            println!("{:#?}", a);
        }),
    };
}

dyn Trait is short for dyn Trait + 'static, in the case of the Fn trait, it means the closure cannot capture anything that is not 'static. this example can be fixed with the following change to the struct definition:

struct C<'a> {
    callback: Box<dyn Fn() + 'a>,
}
4 Likes

Though be aware that you should be very cautious creating types with lifetime parameters, you can never "keep them around" as there's no way to introduce the (non 'static) lifetime. They can only be used as a way to pass data into or (in some cases) out of functions.

You are often better off moving the captured data into the callback by using move || ... instead of || ... though this is more complicated if you're using that captured data elsewhere, be prepared for other trouble.

2 Likes