Rust:可变借用返回不可变借用



抱歉,如果这是问其他地方之前,但我不知道如何搜索这个问题的答案。

我有一段简化的代码,它演示了我在一个较大的软件中遇到的问题。基本上,我有(对我来说)一个项目的两个不可变的借用,然而Rust似乎认为其中一个借用是可变的。

struct SomeStruct {
val: i32
}
fn bor_mut(bor: &mut SomeStruct, new_val: i32) -> &i32 {
bor.val = new_val;
&bor.val
}
fn bor_nmut(bor: &SomeStruct) -> &i32 {
&bor.val
}
fn main() {
// get two non-mutable borrows,
// but one originates from a mutable
// borrow
let mut s = SomeStruct{val: 1};
let a = bor_mut(&mut s, 2);
let b = bor_nmut(&s);
println!("a = {}, b = {}", a, b);
}

编译此代码会产生以下错误:

error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
--> src/main.rs:20:22
|
19 |     let a = bor_mut(&mut s, 2);
|                     ------ mutable borrow occurs here
20 |     let b = bor_nmut(&s);
|                      ^^ immutable borrow occurs here
21 |     println!("a = {}, b = {}", a, b);
|                                - mutable borrow later used here

就是"可变借用"与另一个借用的"可变借用"错误代码。然而,第20行中存在的唯一借用是a,它是不可变的。我明白Rust是从哪里来的了,因为borrow起源于一个不可变的borrow,但我不明白当borrow本身是不可变的时候,这有什么关系?

我认为这是为了防止多线程代码破坏借用检查器的唯一原因,但我似乎想不出一个场景中,这甚至有帮助。然而,如果不是这样的话,这似乎是借用检查器工作方式上的疏忽。

我希望有人能给我解释一下为什么借用检查器是这样工作的?不知怎么的,这是我第一次遇到这个问题。

让我们考虑这个简单的例子:

// We've a buffer with 4 numbers
let mut original_v = vec![0, 1, 2, 3];
// Let's open a scope like if this were the body of a funcion called on `original_v`
{
let exclusive_borrow = &mut original_v;
// Let's take a shared reference to the last element
let shared_borrow_to_first_elem = &v[3];

exclusive_borrow.pop(); // Deletes last element (pointed by the shared reference)
let v2 = *v1; // This now access invalid memory
}

如果上面的代码是可行的,那么创建悬空指针就很容易了,只允许一个独占引用(&mut)或多个共享引用(&),这个问题就消失了。我希望它能帮助你理解这个概念。
我知道在你的例子中,你没有提交任何这些,但是编译器很难检查是否有或是否有那么深的悬空指针,所以它只是创建了一个花哨的规则来防止这个问题。

最新更新