为什么编译器拒绝此代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
错误是:"不能s一次多次借用可变的"(首先借用:m1,第二次借用:) m2.
超出范围s后m1,为什么第一次借用还活着?
我读到了超出原借款人范围的借款范围扩展.然而,这似乎总是涉及原始借款人范围之外的另一个借款人"接管"原始借款,例如,此代码失败并出现完全相同的错误,这对我来说很清楚:
fn main() {
let mut s = 0;
let r: &mut i32;
{
let m1 = &mut s;
r = m1;
}
let m2 = &mut s;
}
Run Code Online (Sandbox Code Playgroud)
在第一个例子中,如果我替换m1.r = &m1.i;为m1.r = &dummy;(dummy定义为some&i32)或with let dummy = &m1.i;,代码编译.仅当我将引用存储在借用结构的另一个字段中时才会发生错误.我不明白为什么这会将借款扩大到其范围之外.
我最好猜测代码的错误是:
s.r最初的生命是整个main,
当我指定m1.r它的引用必须是原始的生命周期,但&m1.i只有m1生命有效.
但我可能错了(错误信息会误导).
首先要注意的是
let mut s = S{i: 0, r: &0};
{
s.r = &s.i;
}
let m2 = &mut s;
Run Code Online (Sandbox Code Playgroud)
给
cannot borrow `s` as mutable because `s.i` is also borrowed as immutable
Run Code Online (Sandbox Code Playgroud)
希望这应该是清楚的 - 如果一个结构自我借用然后它被借用.这指出了为什么任何自借结构基本上没用 - 它不能移动(使其自己的指针无效)也不能和可变引用一起使用.
接下来需要理解来自可变引用的不可变引用计为借入可变引用,因此扩展它.例如
let mut v = ();
let r1 = &(&mut v);
let r2 = &v;
Run Code Online (Sandbox Code Playgroud)
给
cannot borrow `v` as immutable because it is also borrowed as mutable
Run Code Online (Sandbox Code Playgroud)
目前尚不清楚这是否能够合法地成为原始结构的新借款,但它仍然没有这样做.