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);
}
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.
Rc
for child pointers and weak references for parent pointers) won't necessarily work for general graphs. – DetoxifyRc
, just as you suggest; why do you think that's not a valid target? – Vagaryunsafe
keyword allows the programmer to say "no, I guarantee that this code is safe by Rust's safety rules even though the compiler cannot see that it is". You cannot write code that is actually unsafe regardless of how many keywords you add. – Vagary