This is a snippet of Rust code which performs an insertion on a common binary search tree. I want the reference to the branch on which I'll perform the insertion.

struct Node {value: i32,left: Option<Box<Node>>,right: Option<Box<Node>>,}impl Node {fn insert(&mut self, elem: i32) {let ref mut a=if elem < self.value {self.left} else {self.right};// ...}}

This code is invalid. After tweaking it, I came to understand when I perform a if/else statement, Rust moves the content before assigning it. This solution works, but it's really ugly...

let a=if elem < self.value {let ref mut b=self.left;b} else {let ref mut b=self.right;b};

Is there a way to handle the thing without recurring to a Box? I could use a pointer, but it really looks like overkill.

After commenting, this is the entire code

fn insert(&mut self, elem: i32) {let target=if elem < self.value {&mut self.left} else {&mut self.right};match target.as_mut() {None=> {}Some(ref mut node)=> {node.insert(elem);return;}}mem::replace(&mut *target, Some(Box::new(Node::new(elem))));}
  • 1
    I'm not sure why you're using ref keyword. See this playground link that works without it: play.rust-lang.org/… . I assign a to be a mutable reference to either self.left or self.right– turbulencetooFeb 13 at 17:25
  • 2
    TBH as a beginner I find bindings with ref to be confusing and only would use it in a pattern-matching context (match or if let) where I can't get the code to compile without it.– turbulencetooFeb 13 at 17:29
  • Thank you, it works. I think I was just getting confused because after I'm using actually a match... at this point I show the insert code...– G. M.Feb 13 at 17:37
  • As you see, later I do some match etc. I guess I started using ref because the 1st versions didn't work... I smashed my head against the borrow checker so many times I became numb.– G. M.Feb 13 at 17:44
  • 1
    Is that last edit an answer? If so, it doesn't belong in the question. You are welcome to put your own answer below, instead.– ShepmasterFeb 13 at 18:11

As you observed, in your original attempt the "then" and "else" branches both attempt to move the left or right box out of your &mut self borrowed content, and this is not allowed.

let ref mut a=if elem < self.value {self.left} else {self.right};

Your second attempt compiles but is ugly, as you said. This code avoids moving out of the borrowed content by referring to the left and right box by ref mut mutable reference.

let a=if elem < self.value {let ref mut b=self.left;b} else {let ref mut b=self.right;b};

A cleaner way to refer to something by mutable reference is with the &mut operator. The if-statement should be:

let a=if elem < self.value {&mut self.left} else {&mut self.right};

    Your Answer

     

    By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

    Not the answer you're looking for? Browse other questions tagged or ask your own question.