为什么在可变引用上调用方法涉及 "borrowing"?

Why does calling a method on a mutable reference involve "borrowing"?

我正在学习 Rust,我正在尝试将这段代码用于编译:

use std::vec::Vec;
use std::collections::BTreeMap;

struct Occ {
    docnum: u64,
    weight: f32,
}

struct PostWriter<'a> {
    bytes: Vec<u8>,
    occurrences: BTreeMap<&'a [u8], Vec<Occ>>,
}

impl<'a> PostWriter<'a> {
    fn new() -> PostWriter<'a> {
        PostWriter {
            bytes: Vec::new(),
            occurrences: BTreeMap::new(),
        }
    }

    fn add_occurrence(&'a mut self, term: &[u8], occ: Occ) {
        let occurrences = &mut self.occurrences;
        match occurrences.get_mut(term) {
            Some(x) => x.push(occ),
            None => {
                // Add the term bytes to the big vector of all terms
                let termstart = self.bytes.len();
                self.bytes.extend(term);
                // Create a new occurrences vector
                let occs = vec![occ];
                // Take the appended term as a slice to use as a key
                // ERROR: cannot borrow `*occurrences` as mutable more than once at a time
                occurrences.insert(&self.bytes[termstart..], occs);
            }
        }
    }
}

fn main() {}

我收到一个错误:

error[E0499]: cannot borrow `*occurrences` as mutable more than once at a time
  --> src/main.rs:34:17
   |
24 |         match occurrences.get_mut(term) {
   |               ----------- first mutable borrow occurs here
...
34 |                 occurrences.insert(&self.bytes[termstart..], occs);
   |                 ^^^^^^^^^^^ second mutable borrow occurs here
35 |             }
36 |         }
   |         - first borrow ends here

我不明白...我只是在可变引用上调用方法,为什么该行会涉及借用?

I'm just calling a method on a mutable reference, why would that line involve borrowing?

当您调用一个对象的方法时,该对象将改变该对象,您不能任何其他未完成的对象引用。如果这样做,您的变更可能会使这些引用无效并使您的程序处于不一致状态。例如,假设您从哈希图中获取了一个值,然后添加了一个新值。添加新值会达到神奇的限制并强制重新分配内存,您的值现在无处可去!当您使用该值时...程序开始运行!

在这种情况下,您似乎想要执行相对常见的 "append or insert if missing" 操作。您将要为此使用 entry

use std::collections::BTreeMap;

fn main() {
    let mut map = BTreeMap::new();

    {
        let nicknames = map.entry("joe").or_insert(Vec::new());
        nicknames.push("shmoe");

        // Using scoping to indicate that we are done with borrowing `nicknames`
        // If we didn't, then we couldn't borrow map as
        // immutable because we could still change it via `nicknames`
    }

    println!("{:?}", map)
}

因为您正在调用一个借用为可变的方法

昨天我有一个关于哈希的类似问题,直到我在文档中注意到一些东西。 The docs for BTreeMap 显示 insert 的方法签名,以 fn insert(&mut self..

开头

因此,当您调用 .insert 时,您是在隐含地要求该函数借用 BTreeMap 作为可变对象。