Подтвердить что ты не робот

Нельзя заимствовать неизменяемый заимствованный контент как изменчивый

Я пытаюсь разработать приложение для маршрутизации сообщений. Я читал официальные документы Rust и некоторые статьи и думал, что у меня есть то, как указатели, владеющие и заимствованные вещи работают, но поняли, что я этого не сделал.

use std::collections::HashMap;
use std::vec::Vec;

struct Component {
    address: &'static str,
    available_workers: i32,
    lang: i32
}

struct Components {
    data: HashMap<i32, Vec<Component>>
}

impl Components {
    fn new() -> Components {
        Components {data: HashMap::new() }
    }

    fn addOrUpdate(&mut self, component: Component) -> &Components {
        if !self.data.contains_key(&component.lang) {

            self.data.insert(component.lang, vec![component]);
        } else {
            let mut q = self.data.get(&component.lang); // this extra line is required because of the error: borrowed value does not live long enough
            let mut queue = q.as_mut().unwrap();
            queue.remove(0);
            queue.push(component);
        }
        self
    }

}

(Также доступна на игровая площадка)

Выдает ошибку:

error: cannot borrow immutable borrowed content `**queue` as mutable
  --> src/main.rs:26:13
   |
26 |             queue.remove(0);
   |             ^^^^^ cannot borrow as mutable

error: cannot borrow immutable borrowed content `**queue` as mutable
  --> src/main.rs:27:13
   |
27 |             queue.push(component);
   |             ^^^^^ cannot borrow as mutable

Не могли бы вы объяснить ошибку, и было бы здорово, если бы вы могли дать мне правильную реализацию.

4b9b3361

Ответ 1

Ниже приведено небольшое сокращение вашей проблемы:

use std::collections::HashMap;

struct Components {
    data: HashMap<u8, Vec<u8>>
}

impl Components {
    fn add_or_update(&mut self, component: u8) {
        let mut q = self.data.get(&component);
        let mut queue = q.as_mut().unwrap();
        queue.remove(0);
    }
}

fn main() {}

Много раз, когда что-то кажется таким удивительным, полезно распечатать используемые типы. Выделите тип queue:

let mut q: () = self.data.get(&component);
= note: expected type `()`
           found type `&mut &std::vec::Vec<u8>`

У нас есть изменяемая ссылка на неизменяемую ссылку на Vec<u8>. Поскольку мы имеем неизменную ссылку на Vec, мы не можем ее изменить! Изменение self.data.get на self.data.get_mut изменяет тип на &mut &mut collections::vec::Vec<u8> и компилирует код.


Если вы хотите реализовать концепцию "вставить или обновить", вы должны проверить в entry API, что больше эффективный и лаконичный.

Кроме того, Rust использует snake_case для наименования метода, а не camelCase.