是否 'a T 意味着 T: 'a?

10
从我个人的理解和实验来看,这似乎是正确的,但我还没有找到一个权威的来源来证明它。Rust by Example有一个bounds部分,在那里它说:

T: 'a: All references in T must outlive lifetime 'a.

#[derive(Debug)]
struct Ref<'a, T: 'a>(&'a T);
// `Ref` contains a reference to a generic type `T` that has
// an unknown lifetime `'a`. `T` is bounded such that any
// *references* in `T` must outlive `'a`. Additionally, the lifetime
// of `Ref` may not exceed `'a`.
然而,这看起来是一个糟糕的示范,因为T:'a的约束似乎不会影响Ref的行为。我尝试过构建一个比'a更短的T,但无论是否有T:'a,都会受到阻碍。更重要的是,定义一个没有生命周期约束的通用引用可以被当作具有生命周期约束的引用使用。
fn f<'a, T>(r: &'a T) {
    g(r) // this compiles
}

fn g<'a, T: 'a>(r: &'a T) {
    // ...
}

Rust参考手册中的一些示例在泛型参数部分(struct Ref<'a, T> where T: 'a { r: &'a T })中有类似的结构,但没有详细说明。我已经查阅了那里的文档,关于引用和生命周期的文档,但没有找到相关链接。
那么,&'a T是否意味着T: 'a?如果是这样,这在哪里有记录?为什么这些资源有这个不必要的约束?如果不是,规则是什么?

感谢你开启这个话题。对于有中级 Rust 经验的开发者来说,这绝对是有用的。我已经花了将近一周的时间阅读相关内容,但仍然不太清楚。我无法想出一个类型(对于 T)在引用类型中没有使用 T: 'a 约束时无法编译的例子。 - Nawaz
1
从我的下面的回答中,你会发现没有这样的T,因为T: 'a的约束存在于&'a T的使用中。所以明确写出来与不写出来没有区别。 - kmdreko
1个回答

8
是的,&'a T 确实意味着 T: 'a
在此之前,要求引用对象的生命周期必须超过被引用的生命周期,这是为了安全性而必需的。然而,在 Rust 1.31 之前,这个约束没有被推断出来,需要显式地提供,就像 这些 问题 中所示。
正是通过 RFC #2093: 推断生命周期,编译器能够推断出这些约束,并允许用户省略它们。自那时以来,Rust by Example 和 Rust Reference 的片段已经过度规定,不再需要 T: 'a
至少有一个地方,&'a T 不会自动推断出 T: 'a,那就是在为 trait 定义关联类型时(playground 上的示例),但编译器会引导你显式添加它:
trait MakeRef<'a> {
    type Type;
}

impl<'a, T> MakeRef<'a> for Vec<T> {
    type Type = &'a T;
}

error[E0309]: the parameter type `T` may not live long enough
 --> src/lib.rs:6:17
  |
6 |     type Type = &'a T;
  |                 ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
  |
help: consider adding an explicit lifetime bound...
  |
5 | impl<'a, T: 'a> MakeRef<'a> for Vec<T> {
  |           ++++

很棒的回答!关于关联类型缺乏推断,是个bug还是故意的呢?如果是后者,我想知道为什么要这样设计。 - Silvio Mayolo
1
@SilvioMayolo我从RFC中获取了这个信息,所以肯定是有意的:“在这种情况下,impl具有两个输入[MakeRef<'a>Vec<T>]...这两个输入都不要求T:'a”,尽管我不确定为什么更倾向于这样做,是出于设计原因还是技术限制。 - kmdreko
太棒了!感谢你的解释和分享相关的RFC!非常有用。 - Nawaz

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