为什么要求绑定 `T: 'a` 才能存储引用 `&'a T`?

30

给定以下代码:

struct RefWrapper<'a, T> {
    r: &'a T,
}

当编译器出现以下错误时:

error: the parameter type T may not live long enough

consider adding an explicit lifetime bound T: 'a so that the reference type &'a T does not outlive the data it points at.

我已经多次看到这个错误,到目前为止,我只是听从了编译器的指示,一切都顺利完成。然而,仔细思考后,我不明白为什么我要写 T: 'a

就我所理解的而言,已经无法获得这样的引用了。拥有 &'a T 意味着至少有一个类型为 T 的对象存在,它的寿命至少为 'a。但我们不能在该对象中存储任何指向数据的引用,其生命周期短于 'a。这将导致编译器错误。

从这个意义上说,已经无法获得 &'a T,其中 T 不会超过 'a 的寿命。因此,附加的注释 (T: 'a) 不应该是必需的。

我是对的吗? 如果我错了,那么我该如何破坏代码,如果不需要 T: 'a


链接:


2
我在 #rust 上询问了一下,似乎如果取消 T: 'a 的要求,这段代码 就会出问题。但是我现在还不太理解那段代码,所以暂时放弃尝试。希望能有了解该问题的人在此期间回答 ^_^ - Lukas Kalbertodt
2017年8月相关RFC - Lukas Kalbertodt
2个回答

25
这是规范性要求的一部分。如果T:'a(“T超出'a”),则类型&'a T仅在形式上良好(这是必需的,因为我们有一个可以在作用域'a期间访问的引用;指向的值在T中也需要至少在该范围内有效)。
struct RefWrapper<'a, T>是一个通用类型,它表示您可以输入生命周期'x和类型U并获得RefWrapper<'x,U>类型。但是,除非尊重要求T:'a,否则不一定形成此类型甚至实现此类型。
此要求来自实现细节;不一定如在结构体内部使用&'a T这样的T和'a一起使用。必须将形式良好的要求提升到RefWrapper结构的公共接口,以便形成RefWrapper<'_,_>类型的要求是公共的,即使内部实现不是这样。
(还有其他地方会出现相同的要求T:'a,但是是隐含的:
pub fn foo<'a, T>(x: &'a T) { }

我们注意到了一个差异:这里类型&'a T也是公共API的一部分。

15
恭喜你,你是正确的!从Rust 1.31开始,由于RFC 2093,推断结构体上T:'x outlives要求,用户在结构体上输入此限制的要求已被删除:

删除结构体上显式T:'x注释的需要。我们将根据结构体的字段推断它们的存在。简而言之,如果结构体直接或间接地包含引用到具有生命周期'xT,那么我们将推断T:'x是一个要求

基本上,没有不需要这个的情况,所以强制程序员写出来并没有太多价值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接