为啥 Rust 编译器要求我限制泛型类型参数的生命周期(错误 E0309)?

Posted

技术标签:

【中文标题】为啥 Rust 编译器要求我限制泛型类型参数的生命周期(错误 E0309)?【英文标题】:Why does the Rust compiler request I constrain a generic type parameter's lifetime (error E0309)?为什么 Rust 编译器要求我限制泛型类型参数的生命周期(错误 E0309)? 【发布时间】:2016-12-02 06:31:32 【问题描述】:

为什么 Rust 编译器会发出一个错误,要求我在以下结构中限制泛型参数的生命周期?

pub struct NewType<'a, T> 
    x: &'a T,

error[E0309]: the parameter type `T` may not live long enough
 --> src/main.rs:2:5
  |
2 |     x: &'a T,
  |     ^^^^^^^^
  |
  = help: consider adding an explicit lifetime bound `T: 'a`...
note: ...so that the reference type `&'a T` does not outlive the data it points at
 --> src/main.rs:2:5
  |
2 |     x: &'a T,
  |     ^^^^^^^^

我可以通过更改来修复它

pub struct NewType<'a, T>
where
    T: 'a,

    x: &'a T,

我不明白为什么必须将T: 'a 部分添加到结构定义中。我想不出T 中包含的数据比对T 的引用更有效的方法。 x 的引用对象需要比 NewType 结构更长寿,如果 T 是另一个结构,那么它包含的任何引用也需要满足相同的标准。

是否存在需要这种类型的注释的具体示例,或者 Rust 编译器只是迂腐?

【问题讨论】:

这会与关联类型混淆。你必须绑定 ::Associated: 'a 即使你已经绑定了 T 的生命周期,这不会对我来说真的很有意义。 【参考方案1】:

T: 'a 的意思是T 中的任何引用都必须比'a 寿命长。

这意味着你不能这样做:

let mut o: Option<&str> = Some("foo");
let mut nt = NewType  x: &o ;  // o has a reference to &'static str, ok.


    let s = "bar".to_string();
    let o2: Option<&str> = Some(&s);
    nt.x = &o2;

这会很危险,因为nt 在块之后会有一个对s 的悬空引用。在这种情况下,它会抱怨o2 的寿命也不够长。

我想不出一种方法可以让 &amp;'a 引用包含较短生命周期的引用,并且显然编译器知道以某种方式(因为它告诉你添加约束)。但是我认为在某些方面说明限制是有帮助的,因为它使借用检查器不那么神奇:您可以仅从类型声明和函数签名来推断它,而不必查看字段是如何定义的(通常是实现文档中没有的详细信息)或函数的实现方式。

【讨论】:

我同意直言不讳从来都不是一件坏事。我总是问“源是否比目标更长寿”的问题,并且以这种心态很难写出你的例子,因为我隐含地知道编译器会拒绝它。感谢您提供简单而清晰的示例。

以上是关于为啥 Rust 编译器要求我限制泛型类型参数的生命周期(错误 E0309)?的主要内容,如果未能解决你的问题,请参考以下文章

generics - 如何在Rust中添加一个泛型类型实现另一泛型类型的约束?

传递生命周期时,泛型类型参数不受约束

编译时泛型类型大小检查

为啥不总是使用泛型?

如何要求泛型类型在泛型函数中实现 Add、Sub、Mul 或 Div 之类的操作?

Rust编程语言入门之泛型Trait生命周期