Search code examples
rustborrow-checkerownership

How to solve [E0382]: use of moved value in a for loop?


Please help me to solve the following error:

error[E0382]: use of moved value: `nd3`
  --> src/main.rs:21:21
   |
19 |     Node::Y { nd: nd3, max: max } => {
   |                   --- move occurs because `nd3` has type `std::boxed::Box<Node>`, which does not implement the `Copy` trait
20 |       for m in 0..max - 1 {
21 |         match recur(nd3) {
   |                     ^^^ value moved here, in previous iteration of loop

The code is as follows. Please don't mind that the code seems meaningless because I simplified it:

enum Node {
  X { x: usize },
  Y { nd: Box<Node>, max: usize },
  Z { Nd: Vec<Box<Node>> },
}

fn recur(nd: Box<Node>) -> Result<usize, ()> {
  match *nd {
    /// ...
    Node::Y { nd: nd3, max: max } => {
      for m in 0..max - 1 {
        match recur(nd3) {
          Ok(y) => return Ok(y),
          _ => {}
        }
      }
      return Ok(123);
    }
    _ => {}
  }
  return Ok(0);
}


Solution

  • If you have an owned value (nd), and you iterate over it, and then you iterate over it again, you will get an error because it has been moved into the previous iteration of the loop.

    One solution is to derive the Clone trait for Node. Clone is a common trait for the ability to explicitly duplicate an object:

    #[derive(Clone)]
    enum Node {
      X { x: usize },
      Y { nd: Box<Node>, max: usize },
      Z { Nd: Vec<Box<Node>> },
    }
    

    Now you can clone nd3 as you call the function again recursively:

    Node::Y { nd: nd3, max: max } => {
      for m in 0..max - 1 {
        match recur(nd3.clone()) {
          Ok(y) => return Ok(y),
          _ => {}
        }
      }
      return Ok(123);
    }
    

    Now, you are not passing the owned value to the next iteration of the loop. Instead, you are passing an exact duplicate. Another solution would be to borrow the value. However, for smaller objects, cloning is easier.