[rust-dev] Calling a method while iterating over a field of the object

Cameron Zwarich zwarich at mozilla.com
Sun Jun 1 13:03:06 PDT 2014


The simplest thing to do is probably to build an intermediate vector of vertices to insert and then push them all after you are done iterating over the edges.

Cameron

> On Jun 1, 2014, at 12:48 PM, Nicholas Bishop <nicholasbishop at gmail.com> wrote:
> 
> I'm looking for a little borrow-checker advice. Here's a reasonably
> minimal program that demonstrates the problem:
> 
> extern crate collections;
> 
> use collections::HashMap;
> 
> struct G {
>   verts: HashMap<int, String>,
>   edges: Vec<(int, int)>,
> 
>   next_vert_id: int
> }
> 
> impl G {
>   fn new() -> G {
>       G{verts: HashMap::new(), edges: Vec::new(), next_vert_id: 0}
>   }
> 
>   fn add_vert(&mut self, s: &str) -> int {
>       let id = self.next_vert_id;
>       self.next_vert_id += 1;
>       self.verts.insert(id, String::from_str(s));
>       id
>   }
> 
>   fn add_edge(&mut self, v0: int, v1: int) {
>       self.edges.push((v0, v1))
>   }
> }
> 
> fn main() {
>   let mut g = G::new();
> 
>   {
>       let v0 = g.add_vert("vert 0");
>       let v1 = g.add_vert("vert 1");
>       g.add_edge(v0, v1);
>   }
> 
>   for &(v0, v1) in g.edges.iter() {
>       g.add_vert("edge vert");
>   }
> }
> 
> This fails to compile:
> $ rust-nightly-x86_64-unknown-linux-gnu/bin/rustc -v
> rustc 0.11.0-pre-nightly (064dbb9 2014-06-01 00:56:42 -0700)
> host: x86_64-unknown-linux-gnu
> 
> $ rust-nightly-x86_64-unknown-linux-gnu/bin/rustc graph.rs
> graph.rs:39:9: 39:10 error: cannot borrow `g` as mutable because
> `g.edges` is also borrowed as immutable
> graph.rs:39         g.add_vert("edge vert");
>                   ^
> graph.rs:38:22: 38:29 note: previous borrow of `g.edges` occurs here;
> the immutable borrow prevents subsequent moves or mutable borrows of
> `g.edges` until the borrow ends
> graph.rs:38     for &(v0, v1) in g.edges.iter() {
>                                ^~~~~~~
> graph.rs:41:2: 41:2 note: previous borrow ends here
> graph.rs:38     for &(v0, v1) in g.edges.iter() {
> graph.rs:39         g.add_vert("edge vert");
> graph.rs:40     }
> graph.rs:41 }
>           ^
> error: aborting due to previous error
> 
> My understanding of the error is: G::add_vert is being given a mutable
> reference to "g", which means it could do something naughty like clear
> g.edges, which would screw up the loop iteration that is happening in
> main().
> 
> That seems like a pretty reasonable thing to prevent, but it's not
> clear to me how I should restructure the program to work around the
> error. In this minimal example I could copy the code out of
> G::add_vert and stick it directly inside the loop, but that's clearly
> not the general solution.
> 
> Thanks,
> -Nicholas
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev


More information about the Rust-dev mailing list