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

kmd*_*eko 10 lifetime language-lawyer rust

从我自己的理解和实验来看,这似乎是正确的,但我还没有找到记录它的权威来源。Rust by Example 有一个边界部分,其中写道:

T: 'a: 中的所有引用都T必须比生命周期长'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`.
Run Code Online (Sandbox Code Playgroud)

然而,这看起来是一个很糟糕的演示,因为T: 'a界限似乎并不影响 的行为Ref。我尝试构造一个T比 短的 ,'a无论有没有 都会受到阻碍T: 'a更重要的是,一个没有生命周期限制的通用引用可以被当作一个有生命周期的引用来传递:

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

fn g<'a, T: 'a>(r: &'a T) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

《Rust 参考》在通用参数部分 ( )中的一些示例中具有类似的结构struct Ref<'a, T> where T: 'a { r: &'a T },但没有详细说明。我浏览了那里的文档,那些关于参考文献和关于生命周期的文档,但找不到链接。

那么是否&'a T意味着T: 'a?如果是这样,这在哪里记录?为什么这些资源有这种不必要的限制?如果没有,规则是什么?

kmd*_*eko 8

是的,&'a T确实意味着T: 'a

总是要求引用对象的寿命必须超过引用的寿命,因为它对于安全构建是必要的。然而,在 Rust 1.31 之前,不会推断界限,必须明确提供,如这些 问题所示。

RFC #2093: infer outlives让编译器推断这些边界,从而允许用户忽略它们。从那时起,Rust by Examples 和 Rust Reference 片段就被过度指定,并且T: 'a不再需要。

请参阅参考文献中有关特征和生命周期界限的其他部分:

有时会推断出类型良好形成所需的生命周期界限。

fn requires_t_outlives_a<'a, T>(x: &'a T) {}
Run Code Online (Sandbox Code Playgroud)

为了使类型格式良好,类型参数T需要长期存在。这是推断出来的,因为函数签名包含的类型只有在成立时才有效。'a&'a T&'a TT: 'a


至少有一个地方&'a T不会自动推断T: 'a,那就是在为特征定义关联类型时(操场上的演示),但编译器会引导您显式添加它:

trait MakeRef<'a> {
    type Type;
}

impl<'a, T> MakeRef<'a> for Vec<T> {
    type Type = &'a T;
}
Run Code Online (Sandbox Code Playgroud)
fn requires_t_outlives_a<'a, T>(x: &'a T) {}
Run Code Online (Sandbox Code Playgroud)