Struct borrow moved confusion

I'm creating game of life in Rust. But I'm basically stuck due to the borrow part.

#[derive(Clone)]
pub struct World {
    pub cells: Vec<Cell>,
    width: i64,
    height: i64
}
impl World {
...
pub fn next(mut self) {
        //doing this instead of let old_world = self was causing Copy issue
       //hence creating a new old_world
        let old_world = World{
            cells: self.cells.clone(),
            width: self.width,
            height: self.height,
        };

        for y in 0..self.height {
            for x in 0..self.width {
                let mut cell = Cell::new(old_world.get_cell(x, y));
                let count = old_world.find_neighbours(x, y);
                cell.next_state(count);
                self.set_cell(x, y, cell.alive);
            }
        }
    }

and I get following error:

PS C:\Users\ajink\RustProjects\game-of-life> cargo run
   Compiling game-of-life v0.1.0 (C:\Users\ajink\RustProjects\game-of-life)
error[E0382]: use of moved value: `old_world`
  --> src\world.rs:55:42
   |
47 |         let old_world = World{
   |             --------- move occurs because `old_world` has type `world::World`, which does not implement the `Copy` trait
...
55 |                 let mut cell = Cell::new(old_world.get_cell(x, y));
   |                                          ^^^^^^^^^ value used here after move
56 |                 let count = old_world.find_neighbours(x, y);
   |                             --------- value moved here, in previous iteration of loop

error[E0382]: use of moved value: `old_world`
  --> src\world.rs:56:29
   |
47 |         let old_world = World{
   |             --------- move occurs because `old_world` has type `world::World`, which does not implement the `Copy` trait
...
55 |                 let mut cell = Cell::new(old_world.get_cell(x, y));
   |                                          --------- value moved here
56 |                 let count = old_world.find_neighbours(x, y);
   |                             ^^^^^^^^^ value used here after move

error[E0507]: cannot move out of `*self` which is behind a shared reference
  --> src\world.rs:69:30
   |
69 |                 print!("{}", self.get_char(self.get_cell(x, y)));
   |                              ^^^^ move occurs because `*self` has type `world::World`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*self` which is behind a shared reference
  --> src\world.rs:69:44
   |
69 |                 print!("{}", self.get_char(self.get_cell(x, y)));
   |                                            ^^^^ move occurs because `*self` has type `world::World`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*self` which is behind a shared reference
  --> src\world.rs:78:13
   |
78 |         if !self.is_inside(x, y) {
   |             ^^^^ move occurs because `*self` has type `world::World`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*self` which is behind a shared reference
  --> src\world.rs:92:9
   |
92 |         self.is_inside(x+vec.x, y+vec.y) && self.get_cell(x+vec.x, y+vec.y)
   |         ^^^^ move occurs because `*self` has type `world::World`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*self` which is behind a shared reference
  --> src\world.rs:92:45
   |
92 |         self.is_inside(x+vec.x, y+vec.y) && self.get_cell(x+vec.x, y+vec.y)
   |                                             ^^^^ move occurs because `*self` has type `world::World`, which does not implement the `Copy` trait

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0382, E0507.
For more information about an error, try `rustc --explain E0382`.
error: could not compile `game-of-life`.

To learn more, run the command again with --verbose.
PS C:\Users\ajink\RustProjects\game-of-life>
  • World::get_cell should probably take self by reference
  • World::next should probably take self by mutable reference

Similarly for other methods you wrote. You only want self by value if you are consuming self. If you just want to look at or mutate, you do it by (maybe mutable) reference.

1 Like

mut self and &mut self are two different things.

The stand-alone mut doesn't change meaning of the type (it refers to variable name, not type), so it's equivalent to just self, which means the function takes exclusive ownership of self, and destroys it before the end of the function call.

1 Like

So if I just do let old_world = self; //while self = &mut self

Will it not change original World !

@kornel & @RustyYato solution mentioned by both of you worked. I just made the function receive &mut pub fn next(&mut self) { and everywhere else I made the self as &self

Can you guys point me to a article to understand about &mut & & reference understanding :slight_smile: Thanks again

Here's a really good one
https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.