首页 文章

神秘借用范围扩展

提问于
浏览
9

为什么编译器拒绝此代码:

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;
}

错误是:“不能一次多次将 s 借用为可变”(首先借用: m1 ,第二次借用: m2 ) .

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

我读到了超出原借款人范围的借用范围扩展 . 然而,这似乎总是涉及原始借款人范围之外的另一个借款人“接管”原始借款,例如:此代码失败并出现完全相同的错误,这对我来说很清楚:

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

在第一个示例中,如果我将 m1.r = &m1.i; 替换为 m1.r = &dummy; (dummy定义为some&i32)或 let dummy = &m1.i; ,则代码将编译 . 仅当我将引用存储在借用结构的另一个字段中时才会发生错误 . 我不明白为什么这会将借款扩大到其范围之外 .

我最好猜测代码的错误是:

  • s.r 的原始生命周期是整个 main

  • 当我为 m1.r 分配引用时,它必须是原始生命周期,但 &m1.i 仅在 m1 生效时有效 .

但我可能错了(错误信息会误导) .

1 回答

  • 6

    首先要注意的是

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

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

    希望这应该是清楚的 - 如果一个结构自我借用然后它被借用 . 这指出了为什么任何自借结构基本上没用 - 它不能移动(使其自己的指针无效)也不能和可变引用一起使用 .


    接下来需要理解来自可变引用的不可变引用计为借入可变引用,因此扩展它 . 例如

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

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

    目前尚不清楚这是否能够合法地成为原始结构的新借款,但它仍然没有这样做 .

相关问题