鉴于以下防 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 是如何在你的一生中得到满足的?

推荐答案

编译器总是被允许以更短的生存期重新borrow .

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

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

编译器重新编译x(aka (&*x)),其生存期为'v3,短于'v2,这是允许的,因为(推断)方差为Value<'v>(匹配&'v T).


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

  • &'v ()(电流)等于covariant.
  • Cell<&'v ()>等于invariant.
  • fn (&'v ()) -> ()contravariant,是covariant的倒数.

使用invariant Value<'v>可以防止将生命周期 与新的生命周期 统一起来,而使用contravariant Value<'v>只能将生命周期 与greater Value<'v>统一起来.

Rust相关问答推荐

属性宏修改派生宏的派生实现

为什么复印是豆荚的一个重要特征?

下载压缩文件

为什么`Vec i64`的和不知道是`Option i64`?

带参考文献的 rust 元组解构

Trait bound i8:来自u8的不满意

根据填充系数以相对大小在给定空间中布局项目

Rust ndarray:如何从索引中 Select 数组的行

为什么RefCell没有与常规引用相同的作用域?

由于生存期原因,返回引用的闭包未编译

如何将带有嵌套borrow /NLL 的 Rust 代码提取到函数中

在 Rust 中,是否可以定义一个需要实现类型的构造函数的对象安全特征?

可以在旋转循环中调用try_recv()吗?

如何正确使用git2::Remote::push?

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

sha256 摘要仅适用于 &*

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

如何在 Rust 中返回通用 struct

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

覆盖类型的要求到底是什么?为什么单个元素元组满足它?