I want to implement a Timer object, which is owned by Foo object and it should call the Foo object's method periodically. I just implemented adding callback function (which is executing Foo object's method) to the Timer as below, but it failed to compile due to conflicting lifetime requirements.
Code (does not containing executing callback function part)
use std::sync::Mutex;
#[derive(Default)]
struct Timer<'a> {
callbacks: Mutex<Vec<Box<dyn Fn() + 'a>>>,
}
impl<'a> Timer<'a> {
fn add(&self, callback: Box<dyn Fn() + 'a>) {
let mut callbacks = self.callbacks.lock().unwrap();
callbacks.push(callback);
}
}
#[derive(Default)]
struct Foo<'a> {
value: usize,
timer: Timer<'a>,
}
impl<'a> Foo<'a> {
fn callback(&self) {
println!("value is {}", self.value);
}
fn process(&self) {
let callback = || {
self.callback();
};
self.timer.add(Box::new(callback));
}
}
fn main() {
let foo = Foo::default();
foo.process();
}
failed to compile with below error
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:28:24
|
28 | let callback = || {
| ________________________^
29 | | self.callback();
30 | | };
| |_________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 27:5...
--> src/main.rs:27:5
|
27 | fn process(&self) {
| ^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:28:24
|
28 | let callback = || {
| ________________________^
29 | | self.callback();
30 | | };
| |_________^
= note: expected `(&&Foo<'a>,)`
found `(&&Foo<'a>,)`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 22:6...
--> src/main.rs:22:6
|
22 | impl<'a> Foo<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:32:20
|
32 | self.timer.add(Box::new(callback));
| ^^^
= note: expected `&Timer<'_>`
found `&Timer<'a>`
error: aborting due to previous error
I think the error comes from the process method in Foo object takes self as &'_ lifetime, but self.timer need &'a lifetime.
When I added &'a lifetime to self in process and callback method as below,
...
impl<'a> Foo<'a> {
fn callback(&'a self) {
...
}
fn process(&'a self) {
...
}
}
...
Below error occured-
error[E0597]: `self` does not live long enough
--> src/main.rs:29:13
|
22 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
...
28 | let callback = || {
| -- value captured here
29 | self.callback();
| ^^^^ borrowed value does not live long enough
...
32 | self.timer.add(Box::new(callback));
| ------------------ cast requires that `self` is borrowed for `'a`
33 | }
| - `self` dropped here while still borrowed
error[E0597]: `foo` does not live long enough
--> src/main.rs:39:5
|
39 | foo.process();
| ^^^ borrowed value does not live long enough
40 | }
| -
| |
| `foo` dropped here while still borrowed
| borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
error: aborting due to 2 previous errors
How to solve this problem?