为什么链接生命周期只与可变引用有关?

时间:2015-08-23 11:02:29

标签: rust

几天前,有人a question有人对链接的生命周期有一个问题,这个生命周期是一个包含借来的数据本身的类型的可变引用。问题是提供对类型的引用,借用与类型内部借用数据相同的生命周期。 我试图重新创建问题:

struct VecRef<'a>(&'a Vec<u8>);

struct VecRefRef<'a>(&'a mut VecRef<'a>);

fn main() {
    let v = vec![8u8, 9, 10];
    let mut ref_v = VecRef(&v);
    create(&mut ref_v);
}

fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
    VecRefRef(r);
}

Example code

我在'b中明确注释create()。这不编译:

error[E0623]: lifetime mismatch
  --> src/main.rs:12:15
   |
11 | fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
   |                      ------------------
   |                      |
   |                      these two types are declared with different lifetimes...
12 |     VecRefRef(r);
   |               ^ ...but data from `r` flows into `r` here

生命周期'b类似于'b < 'a,因此违反了VecRefRef<'a>中的约束,其生命周期与引用的VecRef<'a>完全相同。

我将可变引用的生命周期与VecRef<'a>

中的借用数据相关联
fn create<'a>(r: &'a mut VecRef<'a>) {
    VecRefRef(r);
}

现在它有效。但为什么?我怎么能提供这样的参考? r内的可变引用create()的生命周期为VecRef<'a>而不是'a。为什么问题没有推到函数create()的调用端?

我注意到另一件我不理解的事情。如果我在VecRefRef<'a>结构中使用 immutable 引用,那么在提供具有不同生命周期'a的引用时,它会以某种方式无关紧要:

struct VecRef<'a>(&'a Vec<u8>);

struct VecRefRef<'a>(&'a VecRef<'a>); // now an immutable reference

fn main() {
    let v = vec![8u8, 9, 10];
    let mut ref_v = VecRef(&v);
    create(&mut ref_v);
}

fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
    VecRefRef(r);
}

Example code

这与VecRefRef<'a>VecRef<'a>的可变引用的第一个示例相反。我知道可变引用具有不同的别名规则(根本没有别名)但是这与链接的生命周期有什么关系呢?

1 个答案:

答案 0 :(得分:5)

  

r内的可变引用create()的有效期为VecRef<'a>而非'a

这是混淆的常见原因。检查此功能定义:

fn identity<'a, T>(val: &'a T) -> &'a T { val }

在函数定义中,'a泛型生命周期参数,它与泛型类型参数(T)平行。调用该函数时,调用者将决定'aT的具体值。让我们回顾一下你的main

fn main() {
    let v = vec![8u8, 9, 10];   // 1 |-lifetime of `v`
    let mut ref_v = VecRef(&v); // 2 |  |-lifetime of `ref_v` 
    create(&mut ref_v);         // 3 |  |
}

v将在main(1-3)的整个过程中生效,但ref_v仅适用于最后两个陈述(2-3)。请注意,ref_v 指的是超过它的值。如果你接着引用ref_v,你就可以参考(2-3)中存在的东西,它本身就是对(1-3)中存在的东西的引用。

查看您的固定方法:

fn create<'a>(r: &'a mut VecRef<'a>)

这表示用于此函数调用,对VecRef的引用及其包含的引用必须相同。有一个生命周期可以满足这个 - (2-3)。

请注意,您的结构定义目前要求两个生命周期相同。你可以让它们有所不同:

struct VecRefRef<'a, 'b: 'a>(&'a mut VecRef<'b>);
fn create<'a, 'b>(r: &'a mut VecRef<'b>)

请注意,您必须使用语法'b: 'a来表示生命周期'b将超过'a

  

如果我使用不可变引用[...],那么它就不再重要了

我不太确定。我相信正在发生的事情是因为你有一个不可变借用,编译器可以自动在较小的范围内重新借用。这样可以使生命周期匹配。正如您所指出的,可变引用不能包含任何别名,即使是具有较小范围的别名,因此在这种情况下编译器也无法提供帮助。