为什么使用特征时参数类型必须是“static”

Fab*_* H. 3 traits lifetime rust

我在摆弄树木和特征时遇到了一种我不理解的行为。这是一个最小的(未编译的)示例:

trait Trait<T> {}
struct Struct<T> {
    option: Option<Box<dyn Trait<T>>>, // change this to Option<Box<TestStruct<T>>>
                                       // and it works without issues
}
impl<T> Trait<T> for Struct<T> {}

fn set<T>(s: &mut Struct<T>) {                         // works when changed to "fn set <T: 'static> ..."
    s.option = Some(Box::new(Struct { option: None })) // "error[E0310]: the parameter type `T` may not live long enough"
}
Run Code Online (Sandbox Code Playgroud)

所以这段代码可以与T: 'staticor 一起使用Option<Box<TestStruct<T>>>,但不能按原样工作,我找不到令人满意的解释。

有人可以解释一下特征和生命周期是怎么回事吗?还有其他方法可以做到这一点吗?

Kev*_*eid 7

每当我们在这里使用特征对象dyn Trait<T>时,我们就放弃了 Rust 通常拥有的关于类型具有哪些特征的大量信息。

\n

特别是,类型的值可能包含引用,在这种情况下,该类型具有一个或多个生命周期,用于指定这些引用的有效时间。(最简单的情况是当类型本身是引用时;&\'a str不能比由\'a

\n

但特征对象并不指定具体类型;它可以是实现该特征的任何类型。这意味着特征对象必须始终考虑具体类型允许包含哪些生命周期。这是通过特征对象的\xe2\x80\x9clifetime绑定\xe2\x80\x9d来完成的。每个特征对象都有一个生命周期绑定\xe2\x80\x94,由于生命周期省略,它经常不被写入它经常不被写入。

\n

特别是,省略规则表明,任何时候你写Box<dyn Trait>,都相当于Box<dyn Trait + \'static>。也就是说,X您想要转换为此特征对象类型的任何类型都必须满足边界X: \'static,这意味着如果它包含任何生命周期,它们必须比\'static\xe2\x80\x94 长,在生命周期的特定情况下\'static,它们是相同的就是说它们必须等于\'static,因为生命周期不会长于\'static

\n

(默认特征对象生命周期界限的另一个常见情况是&\'a dyn Trait,规则使其等效于&\'a (dyn Trait + \'a)\xe2\x80\x94\xc2\xa0 ,允许任何比引用的生命周期长或等于引用生命周期的东西。)

\n

因此,解释一下您所观察到的情况:

\n
    \n
  • 添加T: \'static作品是因为你的TestStruct<T>(你没有给出定义,所以我猜)不包含任何引用,所以T: \'static逻辑上意味着TestStruct<T>: \'static,它满足特征对象生命周期界限。

    \n
  • \n
  • 使用Option<Box<TestStruct<T>>>代替Option<Box<dyn Trait<T>>>意味着不涉及特征对象,因此没有默认\'static绑定,因此Struct<T>完全通用\xe2\x80\x94\xc2\xa0它不关心是否T有任何生命周期。

    \n
  • \n
\n

在大多数情况下,当您想要使用Box<dyn Trait>\xe2\x80\x94\xc2\xa0 将其存储在某些数据结构 \xe2\x80\x94 中时,绑定T: \'static是正确的选择,因为您要存储以供稍后使用的内容通常需要不受特定生命周期的束缚\xe2\x80\x94\xc2\xa0能够永远生存。但是,如果您确实需要承认具有非静态生命周期的类型,则始终可以Box<dyn Trait + \'a>改为编写(前提是\'a声明了生命周期)。

\n