wrestling with borrow checker - rust

I'm new to Rust. As a learning exercise I'm trying to make a basic binary tree. This is what I have so far:
fn main() {
let data = vec![6,1,2,3,4,5];
let mut root = Node::<i32> { value: data[0], left: None, right: None };
for val in data {
createAndInsert::<i32>(&root, val);
}
println!("Root value: {}", root.value);
}
fn createAndInsert<T: PartialOrd>(mut root: &Node<T>, value: T) {
let mut n = Node::<T> { value: value, left: None, right: None };
insert::<T>(&root, &n);
}
fn insert<T: PartialOrd>(mut curr: &Node<T>, new: &Node<T>) {
if new.value > curr.value {
match curr.right {
Some(ref n) => insert(n, new),
None => curr.right = Some(Box::new(*new))
}
} else {
match curr.left {
Some(ref n) => insert(n, new),
None => curr.left = Some(Box::new(*new))
}
}
}
struct Node<T: PartialOrd> {
value: T,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
The compiler errors I'm getting:
test.rs:21:48: 21:52 error: cannot move out of borrowed content
test.rs:21 None => curr.right = Some(Box::new(*new))
^~~~
test.rs:26:47: 26:51 error: cannot move out of borrowed content
test.rs:26 None => curr.left = Some(Box::new(*new))
^~~~
test.rs:21:21: 21:54 error: cannot assign to immutable field `curr.right`
test.rs:21 None => curr.right = Some(Box::new(*new))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.rs:26:21: 26:53 error: cannot assign to immutable field `curr.left`
test.rs:26 None => curr.left = Some(Box::new(*new))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 4 previous errors
I've got myself tangled in all the refs and muts and &'s and *'s and I'm not sure how to get out. Where am I going wrong?

You have two problems:
Cannot move out of borrowed context: see Cannot move out of borrowed content when borrowing a generic type for an explanation.
Cannot assign to immutable field: you only have a &Node<T>; to modify the Node you need a &mut Node<T>. mut curr in the pattern merely makes the binding mutable, meaning that you can assign a new value to curr. You can’t, however, modify the contents of what curr refers to. Propagate the &-to-&mut conversion throughout the code and it’ll work.

Since you are new to Rust it might help to see how I would have written it:
struct Node<T> {
value: T,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
impl<T> Node<T> {
fn new(x: T) -> Node<T> {
Node { value: x, left: None, right: None }
}
fn boxed(x: T) -> Box<Node<T>> {
Box::new(Node::new(x))
}
}
fn insert<T: PartialOrd>(root: &mut Option<Box<Node<T>>>, new: Box<Node<T>>) {
if let Some(ref mut rbx) = *root {
if new.value < rbx.value {
insert(&mut rbx.left, new);
} else {
insert(&mut rbx.right, new);
}
} else {
*root = Some(new);
}
}
fn main() {
let data = vec![6,1,2,3,4,5];
let mut root = None;
for val in data {
insert(&mut root, Node::boxed(val));
}
println!("Root value: {}", root.unwrap().value);
}
I realize that this is more of an exercise but keep in mind that this kind of data structure should not grow beyond a certain tree depth since it might otherwise cause the stack to overflow when the nodes are recursivly deallocated.

Related

Peek inmplementation for linked list in rust

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=693594655ea355b40e2175542c653879
I want peek() to remove the last element of the list, returning data. What am I missing?
type Link<T> = Option<Box<Node<T>>>;
struct Node<T> {
pub data: T,
pub next: Link<T>,
}
struct List<T> {
pub head: Link<T>,
}
impl<T> List<T> {
fn peek(&mut self) -> Option<T> {
let mut node = &self.head;
while let Some(cur_node) = &mut node {
if cur_node.next.is_some() {
node = &cur_node.next;
continue;
}
}
let last = node.unwrap();
let last = last.data;
return Some(last);
}
}
#[test]
fn peek_test() {
let mut q = List::new();
q.push(1);
q.push(2);
q.push(3);
assert_eq!(q.empty(), false);
assert_eq!(q.peek().unwrap(), 1);
assert_eq!(q.peek().unwrap(), 2);
assert_eq!(q.peek().unwrap(), 3);
assert_eq!(q.empty(), true);
}
To save the head, I need to access the elements by reference, but the puzzle does not fit in my head. I looked at "too-many-lists", but the value is simply returned by reference, and I would like to remove the tail element.
To make this work you have to switch from taking a shared reference (&) to a mutable one.
This results in borrow checker errors with your code wihch is why I had to change the while let loop into one
which checks if the next element is Some and only then borrows node's content mutably and advances it.
At last I Option::take that last element and return it's data. I use Option::map to avoid having to unwrap which would panic for empty lists anyways if you wanted to keep your variant you should replace unwrap with the try operator ?.
So in short you can implement a pop_back like this:
pub fn pop_back(&mut self) -> Option<T> {
let mut node = &mut self.head;
while node.as_ref().map(|n| n.next.is_some()).unwrap_or_default() {
node = &mut node.as_mut().unwrap().next;
}
node.take().map(|last| last.data)
}
I suggest something like below, Just because I spent time on it .-)
fn peek(&mut self) -> Option<T> {
match &self.head {
None => return None,
Some(v) =>
if v.next.is_none() {
let last = self.head.take();
let last = last.unwrap().data;
return Some(last);
}
}
let mut current = &mut self.head;
loop {
match current {
None => return None,
Some(node) if node.next.is_some() && match &node.next { None => false, Some(v) => v.next.is_none()} => {
let last = node.next.take();
let last = last.unwrap().data;
return Some(last);
},
Some(node) => {
current = &mut node.next;
}
}
}
}

Can't do breadth-first search on a binary tree in Rust

I've implemented a binary tree in Rust as a learning project but failed to transverse it to print the tree in a breadth-first search fashion.
The issue is that I can't reassign the search queue (children) because it's borrowed and doesn't live long enough.
https://gist.github.com/varshard/3874803cd035e27facb67c59e89c3c1c#file-binary_tree-rs-L39
How can I correct this?
use std::fmt::Display;
type Branch<'a, T> = Option<Box<Node<'a, T>>>;
struct Node<'a, T: PartialOrd + Display> {
value: &'a T,
left: Branch<'a, T>,
right: Branch<'a, T>
}
impl<'a, T: PartialOrd + Display> Node<'a, T> {
fn insert(&mut self, value: &'a T) {
let target_node = if value > self.value { &mut self.right } else { &mut self.left };
match target_node {
Some(ref mut node) => node.insert(value),
None => {
let new_node = Node{ value: value, left: None, right: None};
*target_node = Some(Box::new(new_node))
}
}
}
fn display(&'a self) {
let mut children: Vec<Option<&Node<'a, T>>> = Vec::new();
children.push(Some(self));
while children.len() > 0 {
for child in &children {
match child {
Some(node) => {
print!("{} ", node.value);
},
None => {
print!(" ")
}
}
}
println!("");
// Error: children doesn't live long enough;
children = self.to_vec(&children);
}
}
fn to_vec(&self, nodes: &'a Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
let mut children: Vec<Option<&Node<'a, T>>> = Vec::new();
for node_option in nodes {
match node_option {
Some(node) => {
match &node.left {
Some(left) => {
children.push(Some(left));
match &node.right {
Some(right) => {
children.push(Some(right));
},
None => {
children.push(None);
}
}
},
None => {
children.push(None);
match &node.right {
Some(right) => {
children.push(Some(right));
},
None => {
children.push(None);
}
}
}
}
},
None => {}
}
}
children
}
}
fn main() {
let root_val = 5;
let mut root = Node{ value: &root_val, left: None, right: None };
root.insert(&3);
root.insert(&4);
root.insert(&1);
root.insert(&6);
root.display();
}
Copying my answer from this reddit comment:
There's a way to directly fix your problem, but I think there are better options for making the code easier to write and understand. For the direct fix, you can make some lifetime adjustments. Instead of
fn to_vec(&self, nodes: &'a Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
You need:
fn to_vec<'b>(&self, nodes: &Vec<Option<&'b Node<'a, T>>>) -> Vec<Option<&'b Node<'a, T>>>
What's the difference there? In the first case we're saying that nodes is a &'a Vec. That is, a borrow of a Vec that lives as long as the value references inside your tree. That's a long time to live, and it's what the compiler's getting angry about.
Now, if you just take the 'a off of that &Vec, the compiler complains about something else:
|
42 | fn to_vec(&self, nodes: &Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
| ------------ -------------------------
| |
| this parameter and the return type are declared with different lifetimes...
...
76 | children
| ^^^^^^^^ ...but data from `nodes` is returned here
Maybe this is the error that pushed you to put the 'a on the &Vec in the first place. We need to solve it a different way. The important thing to understand here is that the return value doesn't contain references directly into the nodes vector, but it does contain copies of the nodes vector's contents, the &Node references. We need to tell the compiler that even though the nodes reference doesn't live very long, its contents do live longer. That's why we create the new lifetime 'b in my fix above.
This is objectively very confusing. Personally, I prefer to avoid solving these tricky problems, by just keeping things alive longer instead of reasoning about exactly how long they live. The source of the difficulty is that we're destroying the children vector on line 39. If we were able to keep it around, and just keep emptying it and refilling it, Rust would give us a much easier time. Have you considered using a std::collections::VecDeque instead of a Vec here? You could construct it once outside of your while-loop, and then you could pass &mut children around, without worrying very much about its lifetime. I think a queue is usually the go-to data structure for a breadth-first traversal, with new children added to the back, and the traversal itself reading from the front.

Rust: Implement AVL Tree and error: thread 'main' panicked at 'already borrowed: BorrowMutError'

I have the following tree structure:
use std::cell::RefCell;
use std::rc::Rc;
use std::cmp;
use std::cmp::Ordering;
type AVLTree<T> = Option<Rc<RefCell<TreeNode<T>>>>;
#[derive(Debug, PartialEq, Clone)]
struct TreeSet<T: Ord> {
root: AVLTree<T>,
}
impl<T: Ord> TreeSet<T> {
fn new() -> Self {
Self {
root: None
}
}
fn insert(&mut self, value: T) -> bool {
let current_tree = &mut self.root;
while let Some(current_node) = current_tree {
let node_key = &current_node.borrow().key;
match node_key.cmp(&value) {
Ordering::Less => { let current_tree = &mut current_node.borrow_mut().right; },
Ordering::Equal => {
return false;
}
Ordering::Greater => { let current_tree = &mut current_node.borrow_mut().left; },
}
}
*current_tree = Some(Rc::new(RefCell::new(TreeNode {
key: value,
left: None,
right: None,
parent: None
})));
true
}
}
#[derive(Clone, Debug, PartialEq)]
struct TreeNode<T: Ord> {
pub key: T,
pub parent: AVLTree<T>,
left: AVLTree<T>,
right: AVLTree<T>,
}
fn main() {
let mut new_avl_tree: TreeSet<u32> = TreeSet::new();
new_avl_tree.insert(3);
new_avl_tree.insert(5);
println!("Tree: {:#?}", &new_avl_tree);
}
Building with cargo build is fine, but when I run cargo run, I got the below error:
thread 'main' panicked at 'already borrowed: BorrowMutError', src\libcore\result.rs:1165:5
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace. error: process didn't
exit successfully: target\debug\avl-tree.exe (exit code: 101)
If i just call insert(3), it will be fine and my tree gets printed correctly. However, if I insert(5) after insert(3), I will get that error.
How do I fix that?
Manually implementing data structures such as linked list, tree, graph are not task for novices, because of memory safety rules in language. I suggest you to read Too Many Linked Lists tutorial, which discusses how to implement safe and unsafe linked lists in Rust right way.
Also read about name shadowing.
Your error is that inside a cycle you try to borrow mutable something which is already borrowed as immutable.
let node_key = &current_node.borrow().key; // Borrow as immutable
match node_key.cmp(&value) {
Ordering::Less => { let current_tree = &mut current_node.borrow_mut().right; }, // Create a binding which will be immediately deleted and borrow as mutable.
And I recommend you to read Rust book to learn rust.
First let us correct your algorithm. The following lines are incorrect:
let current_tree = &mut current_node.borrow_mut().right;
...
let current_tree = &mut current_node.borrow_mut().left;
Both do not reassign a value to current_tree but create a new (unused) one (#Inline refers to it as Name shadowing). Remove the let and make current_tree mut.
Now we get a compiler error temporary value dropped while borrowed. Probably the compiler error message did mislead you. It tells you to use let to increase the lifetime, and this would be right if you used the result in the same scope, but no let can increase the lifetime beyond the scope.
The problem is that you cannot pass out a reference to a value owned by a loop (as current_node.borrow_mut.right). So it would be better to use current_tree as owned variable. Sadly this means that many clever tricks in your code will not work any more.
Another problem in the code is the multiple borrow problem (your original runtime warning is about this). You cannot call borrow() and borrow_mut() on the same RefCell without panic(that is the purpose of RefCell).
So after finding the problems in your code, I got interested in how I would write the code. And now that it is written, I thought it would be fair to share it:
fn insert(&mut self, value: T) -> bool {
if let None = self.root {
self.root = TreeSet::root(value);
return true;
}
let mut current_tree = self.root.clone();
while let Some(current_node) = current_tree {
let mut borrowed_node = current_node.borrow_mut();
match borrowed_node.key.cmp(&value) {
Ordering::Less => {
if let Some(next_node) = &borrowed_node.right {
current_tree = Some(next_node.clone());
} else {
borrowed_node.right = current_node.child(value);
return true;
}
}
Ordering::Equal => {
return false;
}
Ordering::Greater => {
if let Some(next_node) = &borrowed_node.left {
current_tree = Some(next_node.clone());
} else {
borrowed_node.left = current_node.child(value);
return true;
}
}
};
}
true
}
//...
trait NewChild<T: Ord> {
fn child(&self, value: T) -> AVLTree<T>;
}
impl<T: Ord> NewChild<T> for Rc<RefCell<TreeNode<T>>> {
fn child(&self, value: T) -> AVLTree<T> {
Some(Rc::new(RefCell::new(TreeNode {
key: value,
left: None,
right: None,
parent: Some(self.clone()),
})))
}
}
One will have to write the two methods child(value:T) and root(value:T) to make this compile.

Borrowed value does not live long enough when adding to a binary tree built on RefCell

I tried to implement an add operation in a binary tree:
use std::cell::RefCell;
use std::cmp::PartialOrd;
type Link<T> = RefCell<Option<Box<Node<T>>>>;
struct Node<T> {
key: T,
left: Link<T>,
right: Link<T>,
}
struct Tree<T> {
root: Link<T>,
}
impl<T> Node<T> {
fn new(val: T) -> Self {
Node {
key: val,
left: RefCell::new(None),
right: RefCell::new(None),
}
}
}
impl<T: PartialOrd> Tree<T> {
fn new() -> Self {
Tree {
root: RefCell::new(None),
}
}
fn add(&self, val: T) {
let mut next = self.root.borrow();
let node = Box::new(Node::new(val));
match next.as_ref() {
None => {
self.root.replace(Some(node));
()
}
Some(root_ref) => {
let mut prev = root_ref;
let mut cur: Option<&Box<Node<T>>> = Some(root_ref);
while let Some(node_ref) = cur {
prev = node_ref;
if node.key < node_ref.key {
next = node_ref.left.borrow();
} else {
next = node_ref.right.borrow();
}
cur = next.as_ref();
}
if node.key < prev.key {
prev.left.replace(Some(node));
} else {
prev.right.replace(Some(node));
}
}
}
}
}
fn main() {}
I don't understand why the next variable doesn't live long enough:
error[E0597]: `next` does not live long enough
--> src/main.rs:36:15
|
36 | match next.as_ref() {
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error[E0597]: `next` does not live long enough
--> src/main.rs:51:27
|
51 | cur = next.as_ref();
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
next lives for the entire scope of the add function and, in my opinion, other variables containing references to it are dropped before next has dropped.
The compiler says that "values in a scope are dropped in the opposite order they are created", suggesting that there is another way to declare variables and to solve this problem, but I don't know how.
The problem I see is that in order to update a leaf node of your tree you have to hold a reference to each intermediate step, not only its parent, because all the links up to the root node must be kept alive while you are updating the value. And Rust lifetimes just cannot do that.
That is, Rust cannot do that in a loop, but it can do that in a recursive function, and a tree is best implemented with a recursive function.
Naturally, your recursive struct is Node, not Tree, but something like this could work (there are many ways to get the borrows to work):
impl<T: PartialOrd> Node<T> {
fn add(&self, val: T) {
let mut branch = if val < self.key {
self.left.borrow_mut()
} else {
self.right.borrow_mut()
};
if let Some(next) = &*branch {
next.add(val);
return;
}
//Separated from the if let so that branch is not borrowed.
*branch = Some(Box::new(Node::new(val)));
}
}
And then, in impl Tree just relay the work to this one.
The code may be simplified a bit if, as other people noted, you get rid of the Tree vs Node and the RefCell...

What is the best implementation of a recursive struct?

I want to implement a Treep by rust. The node struct of Treep is
#[derive(Clone)]
struct TreepNode {
data: i32,
left: Option<Box<TreepNode>>,
right: Option<Box<TreepNode>>,
}
Then I define a function to implement the right rotate operation.
fn rightRotate(&self) -> Box<TreepNode> {
match self.clone().left {
None => return Box::new(self.clone()),
Some(ref mut leftTree) => {
let mut selfTree = self.clone();
selfTree.left = leftTree.right.clone();
leftTree.right = Some(Box::new(selfTree));
return leftTree.clone()
}
}
}
This code can be compiled. However, the code is ugly because there are lot of clone() and Some in it. Is there any better way to optimize the code?
You can avoid clone() if you consume Self:
fn right_rotate(mut self) -> Box<TreepNode> {
match self.left.take() {
None => Box::new(self),
Some(mut left) => {
self.left = left.right.take();
left.right = Some(Box::new(self));
left
}
}
}

Resources