【问题标题】:Rust: Mutable borrow returns non-mutable borrow [duplicate]Rust:可变借用返回非可变借用 [重复]
【发布时间】:2021-03-06 02:08:38
【问题描述】:

抱歉,如果之前有人问过这个问题,但我不知道如何搜索这个问题的答案。

我有一段简化的代码演示了我在一个更大的软件中遇到的问题。基本上,我有(对我而言)似乎是 2 个不可变借用项,但 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 是从哪里来的,因为借用源自不可变的借用,但是当借用本身是不可变的时,我看不出这有什么关系?

我认为这样做的唯一原因是为了防止多线程代码破坏借用检查器,但我似乎无法想到即使在这种情况下也能有所帮助的场景。但是,如果情况并非如此,那么它似乎确实是对借用检查器工作方式的疏忽。

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

【问题讨论】:

  • 是的,这是一个完美的答案,谢谢!

标签: rust borrow-checker


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    相关资源
    最近更新 更多