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

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.

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;
}
}
}
}

Lifetime issue assigning reference from conditional

I'm quite new in Rust and I'm having an issue with lifetimes that I believe I can understand what is happening and why, but can't get around in my head how can I solve it.
For simplicity I created this short "clone" of what I'm actually trying to do, but the real code is using asyc-stripe. Will annotate the example code with the real one in case is relevant.
There is the following structure:
// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/subscription.rs#L385
struct ObjectA<'a> {
field: i32,
object_b_id: Option<&'a str>,
}
// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/subscription.rs#L570
impl<'a> ObjectA<'a> {
fn new(field: i32) -> Self {
return Self {
field,
object_b_id: Default::default(),
};
}
}
// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/subscription.rs#L210
fn persist_obj_a(obj_a: ObjectA<'_>) {}
// ---
// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/payment_method.rs#L18
struct ObjectB {
id: ObjectBId,
}
// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/ids.rs#L518
struct ObjectBId {
value: String,
}
impl ObjectBId {
fn as_str(&self) -> &str {
return self.value.as_str();
}
}
// This is a wrapper around https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/payment_method.rs#L128 that just returns the first one found (id any, hence the Option)
fn load_object_b() -> Option<ObjectB> {
return Some(ObjectB {
id: ObjectBId {
value: String::from("some_id"),
},
});
}
And what I'm trying to do is: load the ObjectB with load_object_b and use its ID into a ObjectA.
Ok, so on to my attempts.
First attempt
fn first_try(condition: bool) {
let mut obj_a = ObjectA::new(1);
if condition {
match load_object_b() {
Some(obj_b) => obj_a.object_b_id = Some(obj_b.id.as_str()),
None => (),
}
}
persist_obj_a(obj_a);
}
In here I get
obj_b.id does not live long enough
Which I can understand, since from what I can understand the obj_b only exists during the match arm and is droped by the end of it.
Second attempt
fn second_try(condition: bool) {
let mut obj_a = ObjectA::new(1);
if condition {
let obj_b = load_object_b();
match obj_b {
Some(ref obj_b) => obj_a.object_b_id = Some(obj_b.id.as_str()),
None => (),
}
}
persist_obj_a(obj_a);
}
Here I get
obj_b.0 does not live long enough
Which I guess it is still the same idea, just in a different place. Since again, from my understanding, obj_b now only lives within the scope of the if condition.
Third and last attempt
I ended up "solving" it with:
fn third_try(condition: bool) {
let mut obj_a = ObjectA::new(1);
let obj_b = load_object_b();
let obj_b_id = match obj_b {
Some(ref obj_b) => Some(obj_b.id.as_str()),
None => None,
};
if condition {
obj_a.object_b_id = obj_b_id;
}
persist_obj_a(obj_a);
}
In here I moved the obj_b to have the same lifetime as obj_a. So it solves the issue that I was having.
My problem with this solution is that I feel that I'm wasting resource doing the (possible expensive) request to load_object_b even if I'm not gonna use it based on the condition.
Not sure if I'm missing something very obvious or just going on the overall wrong direction, but would appreciate some light on what I might be doing wrong.
This should work, I think:
fn third_try(condition: bool) {
let mut obj_a = ObjectA::new(1);
let obj_b = if condition { load_object_b() } else { None };
obj_a.object_b_id = obj_b.as_ref().map (|o| o.id.as_str());
persist_obj_a(obj_a);
}
Rust allows you to have conditionally initialized variables. You can declare obj_b ouside of the if, but only initialize it inside the if. The compiler will ensure you can use it only if it is initialized.
fn second_try(condition: bool) {
let mut obj_a = ObjectA::new(1);
let obj_b;
if condition {
obj_b = load_object_b();
match obj_b {
Some(ref obj_b) => obj_a.object_b_id = Some(obj_b.id.as_str()),
None => (),
}
}
persist_obj_a(obj_a);
}

How to manage properly ownership with borrowing in Rust?

I'm quite newbie in the Rust world and still not fully understand how ownership/borrowing/lifetime works. I have this example to demonstrate a struggle:
struct Node {
value: bool,
next: Option<Box<Node>>
}
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
Some(*next.unwrap())
}
fn main() {
let mut node = Node {
value: false,
next: None
};
let result = populate(&mut node.next);
println!("{}", node.unwrap().value);
println!("{}", result.unwrap().value);
}
I don't understand why move this way works:
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
// *next = result;
Some(*result.unwrap() /* *next.unwrap() */)
}
But another way doesn't:
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
Some(*(*next.as_ref().unwrap())) // or Some(*next.unwrap())
}
How to proper transfer ownership (like in example above) without copying but with borrowing mutating next reference (and not adding extra parameters)? I'm still not clear with this part...
If you want populate to return a reference to the new Node placed inside next, the reference needs to be part of the return type. You can't move (transfer ownership of) the node into next while also returning it; that's not how ownership works:
fn populate(next: &mut Option<Box<Node>>) -> Option<&mut Node> {
// here: ^^^^
You might try to return Some(&mut *next.unwrap()), but that won't work because unwrap takes self by value. Fortunately, there's a convenient function on Option that will take you straight from &mut Option<Box<Node>> to Option<&mut Node>, as_deref_mut:
fn populate(next: &mut Option<Box<Node>>) -> Option<&mut Node> {
let node = Node {
value: true,
next: None,
};
*next = Some(Box::new(node));
next.as_deref_mut()
}
Also read
Cannot move out of borrowed content / cannot move out of behind a shared reference
Learn Rust With Entirely Too Many Linked Lists
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
Some(*result.unwrap() /* *next.unwrap() */)
}
Massaging the code as the compiler suggests may lead to something you wrote. Now, taking it, introducing intermediate variables and annotating types (to see what's going on) gives this:
fn populate2(next: &mut Option<Box<Node>>) -> Option<Node> {
let node : Node = Node { value: true, next: None };
let result : Option<Box<Node>> = Some(Box::new(node));
*next = result;
let next_as_ref : Option<&Box<Node>> = next.as_ref();
let next_as_ref_unwrap : &Box<Node> = next_as_ref.unwrap();
let next_as_ref_unwrap_deref : Box<Node> = *next_as_ref_unwrap; // <- error here!
Some(*next_as_ref_unwrap_deref) // or Some(*next.unwrap())
}
let next_as_ref_unwrap_deref : Box<Node> = *next_as_ref_unwrap; fails, because next_as_ref_unwrap is a borrowed Box<Node>, i.e. a &Box<Node>. Dereferencing (i.e. *) next_as_ref_unwrap tries to move, which cannot be done from a borrowed variable.
The problem is that you have next, which contains (essentially) a Node, however, you want to return a Node. This poses the question: Do you want to return another (i.e. new Node), or do you want to extract (i.e. take) the Node from next and return it. In case you want to take and return it:
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
next.take().map(|boxed_node| *boxed_node)
}
The above code compiles, but is - at least - dubious, as it accepts a next that is essentially used as a local variable and made None afterwards (because we take from it).
You probably want to decide what populate actually should do.
Should it modify None? Why the return value Option<None>? Should it return next's old value? (Why return Option<Node> instead of Option<Box<Node>> then?)
Code:
fn populate_returning_old_val(next: &mut Option<Box<Node>>) -> Option<Node> {
std::mem::replace(
next,
Some(Box::new(Node { value: true, next: None }))
).take().map(|boxed_node| *boxed_node)
}

Borrowing the mutable member used inside the loop

The problem I want to solve is:
Given the recursively nested data structure, eg. a JSON tree, and a path pointing to (possibly non-existent) element inside it, return the mutable reference of the element, that's the closest to given path.
Example: if we have JSON document in form { a: { b: { c: "foo" } } } and a path a.b.d, we want to have a mutable pointer to value stored under key "b".
This is a code snippet, what I've got so far:
use std::collections::HashMap;
enum Json {
Number(i64),
Bool(bool),
String(String),
Array(Vec<Json>),
Object(HashMap<String, Json>)
}
struct Pointer<'a, 'b> {
value: &'a mut Json,
path: Vec<&'b str>,
position: usize
}
/// Return a mutable pointer to JSON element having shared
/// the nearest common path with provided JSON.
fn nearest_mut<'a,'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Pointer<'a,'b> {
let mut i = 0;
let mut current = obj;
for &key in path.iter() {
match current {
Json::Array(array) => {
match key.parse::<usize>() {
Ok(index) => {
match array.get_mut(index) {
Some(inner) => current = inner,
None => break,
}
},
_ => break,
}
} ,
Json::Object(map) => {
match map.get_mut(key) {
Some(inner) => current = inner,
None => break
}
},
_ => break,
};
i += 1;
}
Pointer { path, position: i, value: current }
}
The problem is that this doesn't pass through Rust's borrow checker, as current is borrowed as mutable reference twice, once inside match statement and once at the end of the function, when constructing the pointer method.
I've tried a different approaches, but not figured out how to achieve the goal (maybe going the unsafe path).
I completely misread your question and I owe you an apology.
You cannot do it in one pass - you're going to need to do a read-only pass to find the nearest path (or exact path), and then a read-write pass to actually extract the reference, or pass a mutator function in the form of a closure.
I've implemented the two-pass method for you. Do note that it is still pretty performant:
fn nearest_mut<'a, 'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Pointer<'a, 'b> {
let valid_path = nearest_path(obj, path);
exact_mut(obj, valid_path).unwrap()
}
fn exact_mut<'a, 'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Option<Pointer<'a, 'b>> {
let mut i = 0;
let mut target = obj;
for token in path.iter() {
i += 1;
// borrow checker gets confused about `target` being mutably borrowed too many times because of the loop
// this once-per-loop binding makes the scope clearer and circumvents the error
let target_once = target;
let target_opt = match *target_once {
Json::Object(ref mut map) => map.get_mut(*token),
Json::Array(ref mut list) => match token.parse::<usize>() {
Ok(t) => list.get_mut(t),
Err(_) => None,
},
_ => None,
};
if let Some(t) = target_opt {
target = t;
} else {
return None;
}
}
Some(Pointer {
path,
position: i,
value: target,
})
}
/// Return a mutable pointer to JSON element having shared
/// the nearest common path with provided JSON.
fn nearest_path<'a, 'b>(obj: &'a Json, path: Vec<&'b str>) -> Vec<&'b str> {
let mut i = 0;
let mut target = obj;
let mut valid_paths = vec![];
for token in path.iter() {
// borrow checker gets confused about `target` being mutably borrowed too many times because of the loop
// this once-per-loop binding makes the scope clearer and circumvents the error
let target_opt = match *target {
Json::Object(ref map) => map.get(*token),
Json::Array(ref list) => match token.parse::<usize>() {
Ok(t) => list.get(t),
Err(_) => None,
},
_ => None,
};
if let Some(t) = target_opt {
target = t;
valid_paths.push(*token)
} else {
return valid_paths;
}
}
return valid_paths
}
The principle is simple - I reused the method I wrote in my initial question in order to get the nearest valid path (or exact path).
From there, I feed that straight into the function that I had in my original answer, and since I am certain the path is valid (from the prior function call) I can safely unwrap() :-)

Error: "use of moved value"

I'm currently learning Rust, and am toying around with a simple calculator. When refactoring, I ended up with some code like the following:
enum OptionalToken {
Foo,
Bar
}
fn next_token() -> OptionalToken {
// Read input, classify, return
OptionalToken::Foo
}
trait Stack {
// ...
fn dump (mut self);
}
impl Stack for Vec<f64> {
// ...
fn dump (mut self) {
println!("Stack: size={} [", self.len());
for x in self.iter() {
println!(" {}", x);
};
println!("]");
}
}
fn main() {
let mut stack: Vec<f64> = Vec::new();
loop {
let tok = next_token();
match tok {
OptionalToken::Foo => { stack.dump(); }
OptionalToken::Bar => { stack.pop(); }
}
}
}
The compiler (nightly build) fails with the following error (same error is actually printed twice as I'm doing the same mistake twice):
src/test.rs:38:37: 38:42 error: use of moved value: `stack`
src/test.rs:38 OptionalToken::Foo => { stack.dump(); }
^~~~~
src/test.rs:38:37: 38:42 note: `stack` moved here because it has type `collections::vec::Vec<f64>`, which is non-copyable
src/test.rs:38 OptionalToken::Foo => { stack.dump(); }
What am I doing wrong here? What would I have to modify to get code structured like this to work?
The function signature fn dump(mut self) (or fn dump(self), it makes no difference and frankly I'm surprised that the mut is permitted in the trait) means that the method takes the Stack by value, i.e. moves it.
There is no reason to take ownership. Make the signature fn dump(&self) to be able to call it without moving.
If "moving" is is all Greek to you, see the Ownership chapter in TRPL.

Resources