为什么一个程序在明显的生命周期不匹配的情况下仍能编译?

Why does a program compile despite an apparent lifetime mismatch?

给定以下 Rust 程序:

struct Value<'v>(&'v ());
struct Container {}

impl Container {
    fn get<'v>(&'v self) -> Value<'v> {
        todo!()
    }
    
    fn set<'v>(&'v self, x: Value<'v>) {
        todo!()
    }
}

fn convert<'v1, 'v2>(x: &'v1 Container, env: &'v2 Container) {
    let root: Value<'v2> = env.get();
    x.set(root);
}

我希望 convert 是一个编译时错误,因为 Value<'v2> 被传递给 x.set(),它需要类型 Value<'v1> 的值 - 但它编译成功。 'v1'v2 之间没有子类型关系。 Rust 如何推断出令人满意的生命周期?

总是允许编译器以更短的生命周期重新借用。

在这种情况下,会发生什么:

fn convert<'v1, 'v2>(x: &'v1 Container, env: &'v2 Container) {
    let root: Value<'v2> = env.get();
    x.set(root);
}

编译器是否重新借用 x(又名 (&*x)),其生命周期为 'v3,短于 'v2,由于(推断的)方差,这是允许的Value<'v>(匹配 &'v T)。


可以通过更改内部值来更改 Value<'v> 的推断方差:

  • &'v ()(当前)是协变的
  • Cell<&'v ()>不变的
  • fn (&'v ()) -> ()逆变协变.
  • 的逆

使用不变量 Value<'v>会阻止将生命周期与新生命周期统一,而使用逆变 Value<'v> 只允许使用 更大的 统一生命周期。