Reputation: 1612
Im trying to create a struct that stores 2 closures, each with read references to an parent scope variable where they were created.
After I have closed over the references in the parent scope, how do I make sure they live for the same amount of time as the closures?
For example:
struct S {
x: bool,
}
type Closure = Box<dyn Fn()>;
struct Env {
fn_a: Closure,
fn_b: Closure,
}
fn get_env() -> Env {
let s = S { x: true };
let fn_a = || {
&s.x;
};
let fn_b = || {
&s.x;
};
Env {
fn_a: Box::new(fn_a),
fn_b: Box::new(fn_b),
}
}
fn main() {
let env = get_env();
}
Results in:
error[E0597]: `s` does not live long enough
--> src/main.rs:16:10
|
15 | let fn_a = || {
| -- value captured here
16 | &s.x;
| ^ borrowed value does not live long enough
...
23 | fn_a: Box::new(fn_a),
| -------------- cast requires that `s` is borrowed for `'static`
...
26 | }
| - `s` dropped here while still borrowed```
Upvotes: 0
Views: 433
Reputation: 8214
It depends on your scenario. How long would the returned closures live?
If it lives as long as the Env
value, what about moving s
into the Env
value and accessing s
from the Env
value?
If you don't know (or don't want to spend the trouble to figure out) the lifetime for the closures, a convenient (although slightly less efficient) way is to use Rc
, then move
a clone of the Rc from the results:
use std::rc::Rc;
pub struct S {
x: bool,
}
pub type Closure = Box<dyn Fn()>;
#[allow(unused)]
pub struct Env {
fn_a: Closure,
fn_b: Closure,
}
fn get_env() -> Env {
let s = Rc::new(S { x: true });
let cloned = Rc::clone(&s);
let fn_a = move || {
s.x;
};
let fn_b = move || {
cloned.x;
};
Env {
fn_a: Box::new(fn_a),
fn_b: Box::new(fn_b),
}
}
fn main() {
let _env = get_env();
}
Upvotes: 2