Reputation: 260
I have a struct Foo with a lifetime parameter 'a:
struct Foo<'a> {
/* snip */
}
I want to pass a closure (which encloses some of Foo's fields) to an arbitrary function, for example:
impl Foo<'_> {
// ...
pub fn do_something(&mut self) {
self.some_object.do_something(
Box::new(
|a_parameter| {
self.some_other_object.do_something_else(a_parameter);
}
)
);
}
// ...
}
do_something would be defined something like so:
fn do_something(f: Box<dyn Fn(T)>) { /* snip */ }
The error I get is
cast requires that `'1` must outlive `'static`
Where '1 is the lifetime of the mutable reference to self in the function implemented on Foo itself.
I think the problem is that I need to specify that the closure (inside the box) lives precisely as long as the function (i.e., the scope) in which it is defined. I just don't see how to do this, I tried numerous things, e.g., adding a lifetime parameter to do_something, though, no success.
Thanks!
Edit
a (non working) example:
struct Bar {
num: i32,
}
impl Bar {
fn do_something(&self, f: Box<dyn Fn(i32)>) {
f(self.num);
}
}
struct Foo<'a> {
bar: &'a Bar,
other_num: i32,
}
impl Foo<'_> {
fn do_something(&self) {
self.bar.do_something(
Box::new(|n| {
println!("{}", n + self.other_num);
})
);
}
}
fn main() {
let bar = Bar { num: 123, };
let foo = Foo { bar: &bar, other_num: 456, };
foo.do_something();
}
Upvotes: 0
Views: 145
Reputation: 6651
Because you take the closure as a trait object (Box<dyn Fn(i32)>
), there's an implicit + 'static
bound (Box<dyn Fn(i32) + 'static>
), meaning the closure isn't allowed to borrow any data. But the closure you want to pass borrows from &self
. You can make the parameter more general by using an explicit lifetime:
impl Bar {
fn do_something<'a>(&self, f: Box<dyn Fn(i32) + 'a>) {
// ^^^^ ^^^^^^
// `f` is now allowed to borrow data for any lifetime `'a`
f(self.num);
}
}
which can be elided
impl Bar {
fn do_something(&self, f: Box<dyn Fn(i32) + '_>) {
f(self.num);
}
}
This is a really simple example. In more complex code, the lifetime requirements might be more strict than this.
Upvotes: 2