为什么克隆到 Rc 时 T 必须是“静态”<RefCell<dyn Trait>>?

问题描述 投票:0回答:1

这是我的代码;在

Ref::computed
中,我收到一个错误,
F
U
必须是
'static
:

use std::cell::RefCell;
use std::rc::Rc;

trait Observer<T> {
    fn update(&mut self, v: &T);
}

struct Computed<U, F> {
    value: U,
    callback: F,
}

impl<T, U, F> Observer<T> for Computed<U, F> where F: Fn(&T) -> U {
    fn update(&mut self, v: &T) {}
}

struct Ref<T> {
    value: T,
    observers: Vec<Rc<RefCell<dyn Observer<T>>>>,
}

impl<T> Ref<T> {
    fn computed<U, F>(&mut self, callback: F) -> Rc<RefCell<Computed<U, F>>>
    where
        F: Fn(&T) -> U,
    {
        let s = Rc::new(RefCell::new(Computed {
            value: callback(&self.value),
            callback,
        }));
        self.observers.push(s.clone());
        s
    }
}
error[E0310]: the parameter type `F` may not live long enough
  --> src/lib.rs:34:29
   |
34 |         self.observers.push(s.clone());
   |                             ^^^^^^^^^
   |                             |
   |                             the parameter type `F` must be valid for the static lifetime...
   |                             ...so that the type `F` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
28 |         F: Fn(&T) -> U + 'static,
   |                        +++++++++

error[E0310]: the parameter type `U` may not live long enough
  --> src/lib.rs:34:29
   |
34 |         self.observers.push(s.clone());
   |                             ^^^^^^^^^
   |                             |
   |                             the parameter type `U` must be valid for the static lifetime...
   |                             ...so that the type `U` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
26 |     fn computed<U: 'static, F>(&mut self, callback: F) -> Rc<RefCell<Computed<U, F>>>
   |                  +++++++++

如果我按照错误建议进行操作,那么一切都会成功。

我就是不明白为什么。既然智能ptr拥有

F
的所有权,为什么还需要声明生命周期呢?它必须
'static
?如果有人可以解释,我将不胜感激。

rust traits lifetime
1个回答
2
投票

该错误与对

clone
的调用无关。相反,这是因为您试图将值存储在
self.observers
中。

当您说

dyn Trait
而不指定生命周期时,会添加隐式生命周期,在本例中为
'static
,因此就好像您写了
dyn Trait + 'static
。 因此,
observers
Ref
场的类型实际上是
Vec<Rc<RefCell<dyn Observer<T> + 'static>>>
。 这就是编译器强制您添加
'static
约束的原因,以便您强制转换为
dyn Observer<T>
的类型满足隐式
'static
生命周期界限。

如果你想允许trait对象包含非静态生命周期,你必须这样注释它:

struct Ref<'a, T> {
    value: T,
    observers: Vec<Rc<RefCell<dyn Observer<T> + 'a>>>,
}

完成此操作后,您需要向

impl Ref
块添加适当的生命周期注释。 具体来说,在
Ref::computed
中,您必须添加边界来约束
F
U
的生存时间至少与
Ref
的生命周期参数一样长:

impl<'a, T> Ref<'a, T> {
    fn computed<U, F>(&mut self, callback: F) -> Rc<RefCell<Computed<U, F>>>
    where
        F: Fn(&T) -> U + 'a,
        U: 'a,
    {
        let s = Rc::new(RefCell::new(Computed {
            value: callback(&self.value),
            callback,
        }));
        self.observers.push(s.clone());
        s
    }
}

(游乐场)

© www.soinside.com 2019 - 2024. All rights reserved.