For background context: I am creating an Observer/Subscriber based Global Event System (using single shared event systems). I decided to use FnMut as my callback closure. The lifetime 'a placed at the impl of the makeshift struct Data<'a> should allow the callback parameter in the method mut_func() to live as long as the whole Data struct. Because the callback parameter uses the F generic which is definitely constrained by the lifetime 'a. But the error is still appearing stating that the callback parameter does not live long enough.
I originally used Box<T> as my container for the dyn FnMut(u32), but the Box<T> requires the callback to be 'static (because I am casting the boxed generic into a box trait objects) which in my scenario is not achievable (for readability). I then tried to use Rc<RefCell<T>> which sadly does not support trait objects.
Also, I am using generics for callback parameter because I want that function to have higher readability instead of having to see Box<T> wrapping around an entire closure that will be everywhere, since this Event System will be my central part of my program. I will do anything to make the 'front-end' more readable and cleaner (except for significant performance impact).
Note: This is my example program. I can post the actual program if needed.
Error:
error[E0597]: `callback` does not live long enough
> | impl<'a> Data<'a> {
> | -- lifetime `'a` defined here
> | fn mut_func<F: FnMut(u32) -> () + 'a>(&mut self, mut callback: F) {
> | self.o.push(&mut callback as &mut dyn FnMut(u32) -> ());
> | ------------^^^^^^^^^^^^^------------------------------
> | | |
> | | borrowed value does not live long enough
> | argument requires that `callback` is borrowed for `'a`
> | }
> | - `callback` dropped here while still borrowed
Example:
use std::any::Any;
use std::mem;
use std::rc::Rc;
use std::cell::RefCell;
struct Event<'a> {
obs: Vec<&'a mut dyn FnMut(u32) -> ()>,
}
impl<'a> Event<'a> {
fn subscriber<F: FnMut(u32) -> () + 'a>(&mut self, mut callback: F) {
self.o.push(&mut callback as &mut dyn FnMut(u32) -> ());
}
}
fn main () {
let mut e = Event {obs: Vec::new()};
let x = 3;
e.subscriber(|n| {x+n;});
}
callbacklives long enough, but the problem is you're not storing thecallbackyou received, you're storing it converted to a trait object (dyn) and that trait object's data has to be owned by something.No it doesn't. This compiles:
Then with one more change, your example will compile: define
xbeforeeso thatxlives longer thane:Rust Playground copy