Вопрос:

Почему вызов метода по изменяемой ссылке связан с «заимствованием»?

rust

1387 просмотра

2 ответа

85 Репутация автора

Я изучаю 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

Я не понимаю ... Я просто вызываю метод с изменяемой ссылкой, почему эта строка связана с заимствованием?

Автор: Matt Chaput Источник Размещён: 05.01.2015 10:56

Ответы (2)


9 плюса

187010 Репутация автора

Решение

Я просто вызываю метод с изменяемой ссылкой, почему эта строка связана с заимствованием?

Когда вы вызываете метод объекта, который будет мутировать объект, у вас не будет других ссылок на этот объект. Если вы это сделаете, ваша мутация может лишить законной силы эти ссылки и привести вашу программу в несогласованное состояние. Например, скажем, что вы получили значение из своей хэш-карты, а затем добавили новое значение. Добавление нового значения достигает магического предела и вынуждает перераспределять память, ваше значение теперь указывает в никуда! Когда вы используете это значение ... Взрыв идет программа!

В этом случае, похоже, вы хотите выполнить относительно обычную операцию «добавить или вставить, если отсутствует». Вы хотите использовать 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)
}
Автор: Shepmaster Размещён: 05.01.2015 11:15

1 плюс

77835 Репутация автора

Потому что вы вызываете метод, который заимствует как изменяемый

У меня был похожий вопрос вчера о Хэше, пока я не заметил что-то в документах. Документы для BTreeMap показывают сигнатуру метода для insertначала сfn insert(&mut self..

Поэтому, когда вы вызываете .insert, вы неявно просите эту функцию заимствовать BTreeMap как изменяемый.

Автор: Nathan Long Размещён: 24.05.2015 12:44
Вопросы из категории :
32x32