【问题标题】:When an immutable reference to a mutable reference to a value outside the scope is returned, why is the mutable reference dropped when the scope ends?当返回对作用域外值的可变引用的不可变引用时,为什么在作用域结束时会丢弃可变引用?
【发布时间】:2019-01-06 13:14:11
【问题描述】:
fn main() {
    // block1: fails
    {
        let mut m = 10;

        let n = {
            let b = &&mut m;
            &**b // just returning b fails
        };

        println!("{:?}", n);
    }

    // block2: passes
    {
        let mut m = 10;

        let n = {
            let b = &&m;
            &**b // just returning b fails here too
        };

        println!("{:?}", n);
    }
}

block1 失败并出现以下错误:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:7:22
   |
7  |             let b = &&mut m;
   |                      ^^^^^^ temporary value does not live long enough
8  |             &**b // just returning b fails
9  |         };
   |         - temporary value dropped here while still borrowed
...
12 |     }
   |     - temporary value needs to live until here

我是否正确假设内部不可变引用超出了 block2 范围,而在 block1 中,即使存在外引用呢?

【问题讨论】:

    标签: rust mutable dereference borrowing


    【解决方案1】:

    这里将可变借用视为非Copy 结构(下面的sn-ps 中的S)就足够了,它拥有引用值的所有权。该模型代表了可变借用的排他性。

    基于此模型的推理:在 block2 中 n 是对原始 m 的引用,而在 block1 中 n 最终将是对可变借用拥有的 m 副本的引用。在这两个块中,内部引用在 let-block 的末尾被删除,但只有在 block1 中这会导致问题,因为在 block1 中,n 的引用目标仍然归内部引用所有掉了。

    struct S { m: i32 }
    let mut m = 10;
    
    let n = {
        let s = S { m };
        let b = &s;
        &(*b).m
    }; // s is dropped
    
    println!("{:?}", n);
    

    在上面的 sn-p 中,s 拥有m 的副本的所有权。引用n 将指向n 的副本,当s 被删除时,该副本被删除 - 不允许。如果m 是非复制,m 将被移动到s,这将具有相同的含义。

    在block2中,原m被直接借用而不复制。如果你强制复制,你会得到和block1一样的错误:

    let mut m = 10;
    
    let n = {
        let m2 = m;
        let mut a = &m2;
        let b = &a;
        &**b
    };
    
    println!("{:?}", n);
    

    【讨论】:

    • 什么触发 m 被复制到 block1 中?我的意思是在这种情况下很明显 fn main() { let mut m:i32 = 10; let n = { let b = &mut m; *b = 12; &*b }; println!("{:?}", n); } ,它不是。复制是因为外部引用而触发的吗?
    • 临时可变引用将始终获取它所指向的值的所有权(复制/移动)?
    • 我可以看到&mutS 之间的相似之处,但这不可能是全部。一方面,block1 will work if you remove the extra layer of &,而带有S 的版本仍然无法编译
    • block1 只有 1 &(即&mut)正在工作,因为这里不涉及副本(没有所有权),也没有临时(类似于右值?),我猜。所以这就是为什么我问所有权是否被占用,因为它是一个临时参考。 (我的意思是&&mut
    • @soupybionics 显然,S 过于简单,无法模拟&mut 的完整语义。我的猜测是外部引用迫使编译器将其推理基于更严格的&mut 模型,该模型更接近S,因此不能保证代码是安全的,而在外部引用丢失的情况下编译器可以高级利用其关于&mut 的知识来推断代码确实是安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多