Mysterious borrow scope extension

旧巷老猫 提交于 2021-02-18 21:10:39

问题


Why does the compiler reject this code:

struct S<'a> {
    i: i32,
    r: &'a i32,
}

fn main() {
    let mut s = S{i: 0, r: &0};
    {
        let m1 = &mut s;
        m1.r = &m1.i;
    }
    let m2 = &mut s;
}

The error is: "cannot borrow s as mutable more than once at a time" (first borrow: m1, second borrow: m2).

Why is the first borrow of s still alive after m1 goes out of scope?

I read about borrow scope extension beyond the scope of the original borrower. However, this always seemed to involve another borrower outside the scope of the original borrower that "took over" the original borrow, e.g. this code fails with the exact same error, which is clear to me:

fn main() {
    let mut s = 0;
    let r: &mut i32;
    {
        let m1 = &mut s;
        r = m1;
    }
    let m2 = &mut s;
}

In the first example, if I replace m1.r = &m1.i; with m1.r = &dummy; (dummy defined as some &i32) or with let dummy = &m1.i;, the code compiles. The error occurs only if I store a reference to a field in another field of the borrowed struct. I don't see why this should extend the borrow beyond its scope.

My best guess as to what is wrong with the code is:

  • s.r's original lifetime is the whole of main,

  • when I assign a reference to m1.r it has to be that original lifetime, but &m1.i is only valid for as long as m1 lives.

But I might be wrong (the error message would be misleading then).


回答1:


First note that

let mut s = S{i: 0, r: &0};
{
    s.r = &s.i;
}
let m2 = &mut s;

Gives

cannot borrow `s` as mutable because `s.i` is also borrowed as immutable

Hopefully this should be clear - if a struct self-borrows then it is borrowed. This points out why any self-borrowing structure is basically useless - it cannot be moved (invalidating its own pointer) nor can and mutable reference be taken to it.


Next one needs to understand that immutable references from mutable references count as borrows into the mutable reference, so extend it. For example

let mut v = ();
let r1 = &(&mut v);
let r2 = &v;

gives

cannot borrow `v` as immutable because it is also borrowed as mutable

It's not clear if this is legally able to be a new borrow into the original structure, but it as-yet does not act as such.



来源:https://stackoverflow.com/questions/32151937/mysterious-borrow-scope-extension

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!