Mutability in a struct

156 Views Asked by At

I'm trying to get use a BTreeMap (or HashMap) from within a struct but I can't because it keeps complaining an ownership problem.

cannot move out of `self.vertices` which is behind a shared reference
move occurs because `self.vertices` has type `std::collections::BTreeMap<u32, std::vec::Vec<u32>>`, which does not implement the `Copy` trait
help: consider borrowing here: `&self.vertices`rustc(E0507)
digraph.rs(13, 17): move occurs because `self.vertices` has type `std::collections::BTreeMap<u32, std::vec::Vec<u32>>`, which does not implement the `Copy`

I'm totally confused at this stage.

use std::collections::BTreeMap;

pub struct DirectedGraph {
    vertices: BTreeMap<u32, Vec<u32>>
}

impl DirectedGraph {
    pub fn new() -> DirectedGraph {
        DirectedGraph { vertices: BTreeMap::new() }
    }

    pub fn add_edge(&self, vertex: u32, edge: u32) {
        let v = &self.vertices;
        v.entry(vertex).or_insert(vec!()).push(edge);
    }

    pub fn num_vertices(&self) -> usize {
        self.vertices.len()
    }
}
error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference
  --> src\digraph.rs:14:9
   |
13 |         let v =&self.vertices;
   |                -------------- help: consider changing this to be a mutable reference: `&mut self.vertices`
14 |         v.entry(vertex).or_insert(vec!()).push(edge);
   |         ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable

error: aborting due to previous error
For more information about this error, try `rustc --explain E0596`.
1

There are 1 best solutions below

0
On BEST ANSWER

The problem seems to be that you're trying to mutate something that you have not marked as mutable. The add_edge method clearly has to mutate the struct but you have an &self receiver instead of an &mut self. Upon making that change the code compiles:

use std::collections::BTreeMap;

pub struct DirectedGraph {
    vertices: BTreeMap<u32, Vec<u32>>
}

impl DirectedGraph {
    pub fn new() -> DirectedGraph {
        DirectedGraph { vertices: BTreeMap::new() }
    }

    pub fn add_edge(&mut self, vertex: u32, edge: u32) {
        self.vertices
            .entry(vertex)
            .or_insert(Vec::new())
            .push(edge);
    }

    pub fn num_vertices(&self) -> usize {
        self.vertices.len()
    }
}

playground