I am trying to port a tree into Rust and run into a problem when trying to write fn add_node
Focusing on
fn add_node(&mut self, child: Rc<RefCell<Node>>)
I am trying to update child.parent = self
but it is not possible because I cannot turn &mut self
into Rc<RefCell<Node>>
and parent
is expecting that.
#[derive(PartialEq, Eq, Default)]
struct Point {
x: i64,
y: i64,
}
struct Trees {
tree_roots: Vec<Rc<RefCell<Node>>>,
}
impl Trees {
/// updates `self` by attaching nodes to `self.tree_roots`
fn generate(&mut self) {
let point = Point::default();
let new_parent = Rc::new(RefCell::new(Node::default()));
let new_child = Rc::new(RefCell::new(Node::default()));
self.attach(point, new_child.clone(), new_parent.clone());
// new_parent and new_child needs to be used afterwards
let _ = Rc::downgrade(&new_parent);
let _ = Rc::downgrade(&new_child);
}
/// attach `new_root` to `self`, also mutate `new_child`
fn attach(&mut self, point: Point, new_child: Rc<RefCell<Node>>, new_root: Rc<RefCell<Node>>) {
// dummy condition
let cond = true;
if cond {
*new_root.borrow_mut() = Node::new_logic1();
*new_child.borrow_mut() = Node::new_logic2();
// add `new_child` to `new_root`
new_root.borrow_mut().add_node(new_child);
// push `new_root` to self.tree_roots
self.tree_roots.push(new_root);
} else {
// Some logic returning a new_child
*new_child.borrow_mut() = todo!();
}
}
}
/// A node points to its parent and its children
#[derive(PartialEq, Eq, Default)]
struct Node {
is_root: bool,
point: Point,
parent: Rc<RefCell<Self>>,
children: Vec<Rc<RefCell<Self>>>,
}
impl Node {
fn new(point: Point) -> Self {
Self {
point,
..Default::default()
}
}
/// Some logic creating a Node
fn new_logic1() -> Self {
Self::default()
}
/// Some logic creating a Node
fn new_logic2() -> Self {
Self::default()
}
/// Add `child` to `self.children` and also make `self` the parent of
/// the `child`, i.e. child.parent = self
fn add_node(&mut self, child: Rc<RefCell<Self>>) {
// make sure child is not the same as self
debug_assert!(*child.borrow() != *self);
child.borrow_mut().is_root = false;
// problematic line.
// How to turn `&T` or `&mut T` into Rc<RefCell<T>> to satisfy `self.parent`?
// vvvvvvvvvvvvvvvvvvvvvvvvvvv
child.borrow_mut().parent = Rc::new(RefCell::new(self));
// at last, push `child` to `self.children`
self.children.push(child);
}
}
error[E0308]: mismatched types
--> src/lib.rs:89:58
|
89 | child.borrow_mut().parent = Rc::new(RefCell::new(self));
| ------------ ^^^^ expected `Node`, found `&mut Node`
| |
| arguments to this function are incorrect
|
note: associated function defined here
--> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:820:18
|
820 | pub const fn new(value: T) -> RefCell<T> {
| ^^^