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;});
}
callback
lives long enough, but the problem is you're not storing thecallback
you 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
x
beforee
so thatx
lives longer thane
:Rust Playground copy