fn main() {
    struct Foo<'a, T> {
        a: &'a mut T,
    }
    
    let p1 = 1;
    let mut p2 = &p1;
    {
        let p3 = 2;
        let mut p4 = &p3;
        let mut f = Foo {
            a: &mut p4,
        };
        f.a = &mut p2;
        println!("{}", f.a);
    }
    println!("{}", p2);
}

当运行此程序时,它遇到错误,如:

error[E0597]: `p3` does not live long enough
  --> src/main.rs:10:19
   |
10 |         let mut p4 = &p3;
   |                      ^^^ borrowed value does not live long enough
...
16 |     }
   |     - `p3` dropped here while still borrowed
17 |     println!("{}", p2);
   |                    -- borrow later used here
-- borrow later used here

这是我的第一个问题:为什么会存在这些错误?

如果我注释最后一行,例如:

fn main() {
    struct Foo<'a, T> {
        a: &'a mut T,
    }
    
    let p1 = 1;
    let mut p2 = &p1;
    {
        let p3 = 2;
        let mut p4 = &p3;
        let mut f = Foo {
            a: &mut p4,
        };
        f.a = &mut p2;
        println!("{}", f.a);
    }
    // println!("{}", p2);
}

它运行成功.通过参考rustonomicon

f.a = &mut p2;

&amp;‘a mut T在’a上是协变的,在T上是不变的,它应该不会成功编译.但是成功了,为什么?

如果我注释最后一行,它应该编译不成功.

推荐答案

问题的核心是,f有一个固定的类型Foo<'a, &'b i32>,根据可变引用的变化规则,&'b i32是不变的,因此'b也是不变的.

然而,通过p2p4fT一起用作两个独立的生命周期 .编译器如何 Select ?它不能将p2使用的生存期缩短为p4的生存期,因为p2可以被修改为引用较小生存期的对象,因此p2可以悬停在最后的println!处(考虑一下如果在将f.a赋给&mut p2之后立即添加*f.a = &p3;会发生什么情况).唯一的 Select 是将p4使用的生命周期 加宽以匹配p2.

由于p4必须与p2的生存期匹配,因此p3中的赋值现在太短,因此您会得到您看到的错误.


第二个示例之所以有效,是因为p2使用的生存期不会在内部块中的println!之后延长,因此p3可以满足该生存期.

Rust相关问答推荐

阻止websocket中断的中断中断的终端(操作系统错误4)

当为a Self:IntoIterator设置trait bind `时,获取`a T `不是迭代器"&'"<'>&'

为什么要在WASM库中查看Rust函数需要`#[no_mangle]`?

将内部类型作为参数的泛型 struct 上的方法

在Rust中显式装箱受生存期限制的转换闭包

如何使用盒装枚举进行模式匹配?

除了调用`waker.wake()`之外,我如何才能确保future 将再次被轮询?

带参考文献的 rust 元组解构

有没有一种惯用的方法来判断VEC中是否存在变体?

当对VEC;U8>;使用serde_json时,Base64编码是保护空间的好方法吗?

如何在嵌套的泛型 struct 中调用泛型方法?

在 Rust 中,为什么 10 个字符的字符串的 size_of_val() 返回 24 个字节?

为什么Rust编译器会忽略模板参数应具有静态生命周期?

哪些特征通过 `Deref` 而哪些不通过?

在 Rust 中返回对枚举变体的引用是个好主意吗?

Abortable:悬而未决的期货?

如何在 Rust 的泛型函​​数中同时使用非拥有迭代器和消费迭代器?

当引用不再被borrow 时,Rust 不会得到它

基于名称是否存在的条件编译

为什么在使用 self 时会消耗 struct 而在解构时不会?