了解 Rust 中参数化结构的生命周期

Understanding lifetimes for parameterized structs in Rust

下面的代码

struct Cat<'a, T> {
    coolness: &'a T,
}

抱怨说

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

有了明确的生命周期限制,它就可以编译。当我实例化 T&i32 的结构时,尽管每个引用都有不同的生命周期,但代码会编译。我的理解是编译器认为内部 & 比外部 &:

struct Cat<'a, T>
where
    T: 'a,
{
    coolness: &'a T,
}

fn main() {
    let b = 10;
    {
        let c = &b;
        {
            let fluffy = Cat { coolness: &c };
        }
    }
}

Cat { coolness: &c } 会扩展到 Cat { coolness: &'a &'a i32 } 吗?对于更多嵌套引用,内部引用是否也假定相同的生命周期等等?

Does Cat { coolness: &c } expand to Cat { coolness: &'a &'a i32 }?

是的,Cat 以引用结束。这可以通过以下代码编译来证明:

let fluffy = Cat { coolness: &c };
fn is_it_a_double_ref(_x: &Cat<&i32>) {}
is_it_a_double_ref(&fluffy);

但是,每个引用的生命周期不一定相同。

My understanding is that the compiler sees that the inner & outlives the outer &

没错。而这正是 T: 'a 边界发挥作用的地方。

一开始生命周期边界有点难以理解。他们对 T 中包含的引用进行了限制。例如,给定绑定 T: 'static,不包含任何引用或仅包含 'static 引用的类型,例如i32&'static str 满足边界,而包含非 'static 引用的类型,例如&'a i32,不要,因为'a: 'static是假的。更一般地,给定边界 T: 'a,类型 T 满足边界,如果对于 T 上的每个生命周期参数 'x'x: 'a 为真(具有没有生命周期参数平凡地满足界限)。

现在回到你的代码。让我们给这些引用起一些名字。我们会说 coolness 的类型是 &'fluffy &'c i32'c 是变量的生命周期 c'fluffy 是变量的生命周期 fluffy (违反直觉,生命周期编码的是借用的范围,而不是指代对象的生命周期,尽管编译器会检查借用不会超出引用对象的生命周期)。这意味着 Fluffy 的类型是 Cat<'fluffy, &'c i32>&'c i32: 'fluffy是真的吗?

要检查&'c i32: 'fluffy是否为真,我们需要检查'c: 'fluffy是否为真。 'c: 'fluffy 为真,因为变量 cfluffy.

之后超出范围