为啥需要绑定 `T: 'a` 来存储引用 `&'a T`?

Posted

技术标签:

【中文标题】为啥需要绑定 `T: \'a` 来存储引用 `&\'a T`?【英文标题】:Why is the bound `T: 'a` required in order to store a reference `&'a T`?为什么需要绑定 `T: 'a` 来存储引用 `&'a T`? 【发布时间】:2017-06-07 06:44:48 【问题描述】:

鉴于此代码:

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

...编译器抱怨:

错误:参数类型T 的寿命可能不够长

考虑添加一个显式的生命周期绑定 T: 'a,这样引用类型 &amp;'a T 的寿命就不会超过它指向的数据。

我已经多次看到这个错误,到目前为止,我只是听了编译器,一切正常。不过想多了,我不明白为什么一定要写T: 'a

据我了解,已经不可能获得这样的参考。拥有&amp;'a T 意味着有一个T 类型的对象至少存在'a。但是我们不能在所述对象中存储任何指向生命周期比'a 更短的数据的引用。这将已经导致编译器错误。

从这个意义上说,已经不可能得到一个&amp;'a T,而T 的寿命不超过'a。因此不需要额外的注释 (T: 'a)。

我说的对吗?我错了吗,如果是的话:如果不需要T: 'a,我怎么能破解代码?


链接:

RFC introducing the syntax Another maybe related RFC

【问题讨论】:

我在#rust 上问过,如果取消T: 'a 的要求,似乎this code 会破坏事情。但我还没有真正理解该代码,我现在将停止尝试。希望了解问题的人同时回答^_^ Related RFC from August 2017 【参考方案1】:

恭喜你,你是对的!从 Rust 1.31 开始,感谢 RFC 2093, Infer T: 'x outlives requirements on structs,删除了用户输入此限制的要求:

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

基本上,没有不需要这样做的情况,所以强迫程序员写出来没有多大价值。

【讨论】:

【参考方案2】:

这是良构规则的一部分。 &amp;'a T 类型只有在 T: 'a (“T 比 'a 寿命更长”;它是必需的,因为我们有一个可以在'a 范围内访问的引用;T 中的指向值也需要至少在该范围内有效)。

struct RefWrapper&lt;'a, T&gt; 是一个泛型类型,它表示您可以输入一个生命周期 'x 和一个类型 U 并返回一个 RefWrapper&lt;'x, U&gt; 类型。但是,除非满足T: 'a 的要求,否则这种类型不一定是格式良好的,甚至不一定是实现的。

这个要求来自一个实现细节;在结构内部,T'a 不一定像 &amp;'a T 一样一起使用。格式良好的要求需要提升到RefWrapper结构的公共接口,这样形成RefWrapper&lt;'_, _&gt;类型的要求是公共的,即使内部实现不是。

(还有其他地方同样的要求T: 'a又回来了但是是隐含的:

pub fn foo<'a, T>(x: &'a T)  

我们发现了一个不同之处:这里的 &amp;'a T 类型也是公共 api 的一部分。)

【讨论】:

以上是关于为啥需要绑定 `T: 'a` 来存储引用 `&'a T`?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++ 不允许重新绑定引用?

为啥需要 Elixir 捕获运算符来将函数绑定到值

为啥在这个例子中需要后期绑定? [复制]

为啥非常量引用不能绑定到临时对象?

为啥在 ObservableCollection 中引用该属性时,此绑定不起作用?

为啥在特殊成员函数中将 r 值绑定到 const 左值引用是非法的?