I am implementing binary tree functionality for a Node struct, more precisely the size of the tree rooted by any given node. The relevant code looks like this:
use std::rc::{Rc, Weak};
use std::cell::RefCell;
type Link<T> = Rc<RefCell<Node<T>>>;
type WeakLink<T> = Weak<RefCell<Node<T>>>;
pub struct Node<T> {
value: T,
parent: Option<WeakLink<T>>,
left: Option<Link<T>>,
right: Option<Link<T>>,
}
impl<T> Node<T> {
pub fn size(link: &Link<T>) -> usize {
let mut size = 0;
let mut links = vec![Rc::clone(link)];
let mut link;
while links.len() > 0 {
size += 1;
link = links.remove(0);
if let Some(left_link) = &link.borrow().left {
links.push(Rc::clone(left_link));
}
if let Some(right_link) = &link.borrow().right {
links.push(Rc::clone(right_link));
}
}
size
}
}
This actually works as intended, but I wondered if it would be possible to do it without the link
variable. Inspired by the help from a user in this forum, I went for this:
pub fn size(link: &Link<T>) -> usize {
let mut size = 0;
let mut links = vec![Rc::clone(link)];
// LINK NOT DECLARED HERE ANYMORE
while links.len() > 0 {
size += 1;
let link = links.remove(0); // LINK NOW DECLARED HERE
if let Some(left_link) = &link.borrow().left {
links.push(Rc::clone(left_link));
}
if let Some(right_link) = &link.borrow().right {
links.push(Rc::clone(right_link));
}
drop(link); // IF THIS IS TO WORK, IT SHOULD BE DROPPED HERE. BUT WHY?
}
size
}
This doesn't work unless I drop link
right before the end of the block. Isn't link going to be dropped anyway immediately after the second if let
anyway?
But there's even more wizardy waiting:
pub fn size(link: &Link<T>) -> usize {
let mut size = 0;
let mut links = vec![Rc::clone(link)];
while links.len() > 0 {
size += 1;
let link = links.remove(0);
if let Some(left_link) = &link.borrow().left {
links.push(Rc::clone(left_link));
}
if let Some(right_link) = &link.borrow().right {
links.push(Rc::clone(right_link));
}; // JUST ADD THIS SEMICOLON AND IT WORKS TOO???
}
size
}
Remove the drop
, add ;
at the end of the second if let
and it works too!
At this point I am completely lost about what Rust is doing, I suspect that the second and third definitions are somehow doing the exact same thing but I fail to see why. Any light casted over this will be very welcomed.