10

I need to define a binary search tree where each node has access to the parent:

enum Tree<'a> {
    Leaf,
    Node {
        left: Box<Tree<'a>>,
        right: Box<Tree<'a>>,
        parent: &'a Tree<'a>,
        data: u64,
    }
}

impl <'a> Tree<'a> {
    pub fn new(data: u64, parent: &'a Tree) -> Tree<'a> {
        Tree::Node {
            left: Box::new(Tree::Leaf),
            right: Box::new(Tree::Leaf),
            parent,
            data
        }
    }
    pub fn insert_at_left_leaf(&'a mut self, data: u64) {
        match *self {
            Tree::Leaf => panic!("Leaf has no children"),
            Tree::Node {ref mut left, ..} => {
                **left = Tree::new(data, self);
            }
        }
    }
}

fn main() {
    let parent = Tree::Leaf;
    let mut t = Tree::Node {
        left: Box::new(Tree::Leaf),
        right: Box::new(Tree::Leaf),
        parent: &parent,
        data: 1u64
    };
    t.insert_at_left_leaf(2);
}

playground

However, I get the following compilation error:

error[E0502]: cannot borrow `*self` as immutable because `self.left` is also borrowed as mutable
  --> src/main.rs:24:42
   |
23 |             Tree::Node {ref mut left, ..} => {
   |                         ------------ mutable borrow occurs here
24 |                 **left = Tree::new(data, self);
   |                                          ^^^^ immutable borrow occurs here
25 |             }
26 |         }
   |         - mutable borrow ends here

What is the paradigmatic way to do this in safe Rust? Specifically, when I insert a new node as the leaf of an existing node, I do not want to re-allocate space for it. There is already space allocated for the Leaf and I want to simply overwrite it with the new node.

14
  • 4
    That's not a tree. If it has a parent pointer, it's a graph, not a tree. Commented Jul 14, 2017 at 17:52
  • 32
    I disagree. Having a parent pointer is an implementation detail. Ultimately what makes the data structure a tree or a graph is the API it exposes (i.e. from the user's standpoint are their cycles or not in the data structure?). Commented Jul 14, 2017 at 17:54
  • 3
    @Shepmaster I looked at the other duplicate which said that it is impossible in safe Rust. By the way, the Rust documentation refers to a tree with parent pointers as a tree, not a graph: doc.rust-lang.org/std/rc/struct.Weak.html Commented Jul 14, 2017 at 18:03
  • 1
    I didn't say it was unsafe. You can totally have a value contain a reference to itself, so long as you never modify or move it, which is not what most people want. See Why can't I store a value and a reference to that value in the same struct? for details — your parent would store a child which would have a reference to the parent, thus you are storing a reference to yourself. Commented Jul 14, 2017 at 18:07
  • 3
    I don't agree that this is a duplicate of either of the marked questions. I've nominated for reopening. Commented Jul 14, 2017 at 20:53

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.