Rust 说函数参数的寿命不够,即使已经放置了适当的寿命

Rust says the function parameter does not live enough, even though proper lifetime have been placed

对于背景上下文:我正在创建一个基于 Observer/Subscriber 的全局事件系统(使用单个共享事件系统)。我决定使用 FnMut 作为我的回调闭包。放置在临时结构 Data<'a>impl 处的生命周期 'a 应该允许方法 mut_func() 中的 callback 参数与整个 Data 结构。因为 callback 参数使用 F 泛型,它肯定受到生命周期 'a 的约束。但是错误仍然出现,指出 callback 参数的寿命不够长。

我最初使用 Box<T> 作为 dyn FnMut(u32) 的容器,但是 Box<T> 要求回调为 'static(因为我将盒装泛型转换为一个框特征对象)在我的场景中是无法实现的(为了可读性)。然后我尝试使用 Rc<RefCell<T>>,遗憾的是它不支持特征对象。

此外,我对 callback 参数使用泛型,因为我希望该函数具有更高的可读性,而不是必须看到 Box<T> 环绕整个闭包 无处不在,因为这个事件系统将是我程序的核心部分。我会尽一切努力使 'front-end' 更具可读性和更清晰(除了显着的性能影响)。

注意:这是我的示例程序。如果需要,我可以 post 实际程序。

错误:

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  

示例:

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;});
}

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.

callback 寿命足够长,但问题是您没有存储收到的 callback,而是存储它 转换为特征对象 (dyn) 并且该特征对象的数据必须归某物所有。

I originally used Box<T> as my container for the dyn FnMut(u32), but the Box<T> requires the callback to be 'static

不,不是。这编译:

struct Event<'a> {
    obs: Vec<Box<dyn FnMut(u32) -> () + 'a>>,
}

impl<'a> Event<'a> {
    fn subscriber<F: FnMut(u32) -> () + 'a>(&mut self, callback: F) {
        self.obs.push(Box::new(callback));
    }
}

然后再进行一项更改,您的示例将编译:在 e 之前定义 x 以便 xe 寿命更长:

fn main() {
    let x = 3;
    let mut e = Event {obs: Vec::new()};
    e.subscriber(|n| {x+n;});
}

Rust Playground copy