0

I'm working on a binary search tree implementation in Rust and I'm trying to implement a function that swaps child nodes.

#[derive(Default)]
pub struct Node {
    data: i32,
    left: Option<Box<Node>>,
    right: Option<Box<Node>>
}

impl Node {
    fn print_data(&self) -> i32 {
        self.data
    }

    fn default() -> Node { //function to help when instantiate node with no children
        Node {
            data: 0,
            left: None,
            right: None
        }
    }

    fn set_left(&mut self, new_left: Option<Box<Node>>) -> () {
       // If self.left was already a pointer, now we're losing it
       // (memory leak).
       self.left = new_left
        // Node {data: self.data, left: new_left, right: &self.right}
    }
    fn set_right(&mut self, new_right: Option<Box<Node>>) -> () {
       self.right = new_right
    }

    fn swap_childs(&mut self) -> () {
        let tmpr = Some(self.right.unwrap());
        let tmpl = Some(self.left.unwrap());
        let nilr = self.right.take();
        let nill = self.left.take();
        self.right = tmpl;
        self.left = tmpr;
    }
}

Here's the error I'm getting:

error[E0507]: cannot move out of `self.right` which is behind a mutable reference
  --> src/main.rs:43:19
   |
43 |         let tmpr = Some(self.right.unwrap());
   |                         ^^^^^^^^^^
   |                         |
   |                         move occurs because `self.right` has type `std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait
   |                         help: consider borrowing the `Option`'s content: `self.right.as_ref()`

error[E0507]: cannot move out of `self.left` which is behind a mutable reference
  --> src/main.rs:44:19
   |
44 |         let tmpl = Some(self.left.unwrap());
   |                         ^^^^^^^^^
   |                         |
   |                         move occurs because `self.left` has type `std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait
   |                         help: consider borrowing the `Option`'s content: `self.left.as_ref()`

Through a lot of trial and error, I'm aware that my struct can't implement the Copy trait since I'm using Option. This is why I assume that the best way to make this change is within the struct, hence the impl function swap_childs. Is there a better way to do this? Is this function even possible using just Option and Box without using other types like Rc?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Oneiros
  • 143
  • 1
  • 13
  • 2
    Did you consider using `std::mem::swap()`? – Sven Marnach Apr 06 '20 at 14:25
  • The duplicates [applied to your situation](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3a3dc146adcde46a56c8005c12b92e8c) – Shepmaster Apr 06 '20 at 14:29
  • See also [Cannot cannot move out of value which is behind a shared reference when unwrapping](https://stackoverflow.com/q/32338659/155423) – Shepmaster Apr 06 '20 at 14:32
  • 1
    *now we're losing it (memory leak)* — there's no memory leak here. *can't implement the `Copy` trait since I'm using `Option`* — this isn't true; `Option` implements `Copy` just fine. *`fn default()`* — this should be an implementation of the [`Default` trait](https://doc.rust-lang.org/std/default/trait.Default.html) and you might as well use `#[derive(Default)]`. – Shepmaster Apr 06 '20 at 14:35

0 Answers0