I am writing a tree in Rust and I want to implement a function:left which can turn a tree's root into the tree's root's left child.
Here is my code:
struct Node {
value: i32,
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}
struct Tree {
root: Option<Box<Node>>,
}
enum Error {
DuplicateValue,
NotFound,
EmptyTree
}
impl Tree {
fn left(&mut self) -> Result<(), Error> {
match self.root {
Option::None => return Err(Error::EmptyTree),
Option::Some(ref mut node) => {
*node = node.left.as_ref().unwrap();
return Ok(())
}
}
}
}
and the error says
mismatched types
expected struct `Box<Node>`
found reference `&Box<Node>`
I have tried many methods and look up a lot of information but I still cannot fix this. I think it is a very simple thing in C, just like:
*root = *(root->left);
but why is it so hard in Rust? Can anyone help me?
Since your code looks like it throws away the whole right branch and the root node when calling left, i.e. you aren't concerned with the original root (it will be dropped after the assignment), you can simply take the left node out of the Option:
impl Tree {
fn left(&mut self) -> Result<(), Error> {
match self.root {
Option::None => Err(Error::EmptyTree),
Option::Some(ref mut node) => {
*node = node.left.take().unwrap();
Ok(())
}
}
}
}
Playground
Note however that this will panic if the left subtree is empty. If you want to make self empty in this case, you want to replace the whole Option, not the value inside it. In this case, you have to first do the matching, return early in the empty case, and only then, after the root is no longer borrowed, do the replacement:
impl Tree {
fn left(&mut self) -> Result<(), Error> {
let node = match self.root {
Option::None => return Err(Error::EmptyTree),
Option::Some(ref mut node) => node.left.take(),
};
self.root = node;
Ok(())
}
}
You probably want to replace the entire Option in self.root, not just the value inside the Some() (so that even when left is None, you don't panic but assign it to self.root).
The second problem you're facing is that you have to move the left branch out from the old root in order to be able to give its ownership to self.root. Normally, you wouldn't be able to do that, since you only have a mutable reference. Fortunately Option::take() is here to help: it lets you take ownership of a value in a &mut Option, changing it to None.
Now that you own the old tree, you can easily assign its left subtree to self.root.
Finally, instead of the match thing you had, you can just convert the Option into a Result via Option::ok_or() and short-circuit or extract the value with ?:
fn left(&mut self) -> Result<(), Error> {
let old_root = self.root.take().ok_or(Error::EmptyTree)?;
self.root = old_root.left;
Ok(())
}
Use clone() with #[derive(Clone)]
#[derive(Clone)]
struct Node {
value: i32,
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}
struct Tree {
root: Option<Box<Node>>,
}
enum Error {
DuplicateValue,
NotFound,
EmptyTree
}
impl Tree {
fn left(&mut self) -> Result<(), Error> {
match self.root {
Option::None => return Err(Error::EmptyTree),
Option::Some(ref mut node) => {
*node = node.left.clone().unwrap();
return Ok(())
}
}
}
}
Related
This question already has answers here:
How to handle "temporary value dropped" error when adapting Box-based tree structure to Rc+RefCell?
(2 answers)
Closed last month.
I was following this other post: Understanding Rust `Rc<RefCell<_>>` where op tried implementing a tree with Box and was successful in doing it but then tried implementing it with Rc and RefCell and found issues. The accepted answer compiles but doesn't work because it doesn't add nodes to the root. I tried updating the accepted answer a bit to try and get it to work but wasn't able to. Basically I'm trying to get mutable references in the loop and I can't because I borroed an immutable reference. But then if a borrow_mut() I get that value is a private field, so I'm assuming I can't access any properties of the contained value if it is a mutable reference?
What should I do to get this code to work?
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
use std::fmt;
#[derive(Debug, Clone)]
pub(crate) struct TreeBox<T> {
root: Option<Box<NodeBox<T>>>,
}
#[derive(Debug, Clone)]
struct NodeBox<T> {
value: T,
left: Option<Box<NodeBox<T>>>,
right: Option<Box<NodeBox<T>>>,
}
impl<T: Ord> TreeBox<T> {
fn new() -> Self {
Self { root: None }
}
pub fn insert(&mut self, value: T) -> bool {
let mut node = &mut self.root;
while let Option::Some(current_node) = node {
match current_node.value.cmp(&value) {
Ordering::Less => node = &mut current_node.right,
Ordering::Equal => return false,
Ordering::Greater => node = &mut current_node.left,
}
}
*node = Option::Some(Box::new(NodeBox {
value,
left: Option::None,
right: Option::None,
}));
return true;
}
}
#[derive(Debug, Clone)]
pub(crate) struct Tree<T> {
root: Option<Rc<RefCell<Node<T>>>>,
}
#[derive(Debug, Clone, PartialEq)]
struct Node<T> {
value: T,
left: Option<Rc<RefCell<Node<T>>>>,
right: Option<Rc<RefCell<Node<T>>>>,
}
impl<T: Ord + fmt::Debug> Tree<T> {
fn new() -> Self {
Self { root: None }
}
pub fn insert(&mut self, value: T) -> bool {
let mut node = &mut self.root;
while let Some(current_node) = node {
let current_node = current_node.borrow();
let cmp = current_node.value.cmp(&value);
let new_node = match cmp {
Ordering::Less => &mut current_node.left,
Ordering::Equal => return false,
Ordering::Greater => &mut current_node.right,
};
node = new_node;
}
// let mut node = &mut node;
*node = Some(Rc::new(RefCell::new(Node {
value,
left: None,
right: None,
})));
println!("node: {:?}", node);
true
}
}
fn main() {
let mut tree_box = TreeBox::new();
tree_box.insert(1);
tree_box.insert(2);
tree_box.insert(3);
let mut tree = Tree::new();
tree.insert(1);
tree.insert(2);
tree.insert(3);
println!("TreeBox: {:?}", tree_box);
println!("Tree: {:?}", tree);
}
The accepted answer compiles but doesn't work because it doesn't add nodes to the root.
You are right, and fixing the original solution, here a version that add the root node correctly:
pub fn insert(&mut self, value: T) -> bool {
//if no root, just create one
let mut node = if let Some(root) = &self.root {
Rc::clone(root)
} else {
self.root = Some(Rc::new(RefCell::new(Node {
value,
left: None,
right: None,
})));
return true;
};
loop {
let current_node = Rc::clone(&node);
let mut current_node = RefCell::borrow_mut(¤t_node);
let cmp = current_node.value.cmp(&value);
let next_node = match cmp {
Ordering::Less => &mut current_node.left,
Ordering::Equal => return false,
Ordering::Greater => &mut current_node.right,
};
if let Some(next_node) = next_node {
node = Rc::clone(next_node);
} else {
*next_node = Some(Rc::new(RefCell::new(Node {
value,
left: None,
right: None,
})));
println!("node: {:?}", node);
return true;
}
}
}
Basically I'm trying to get mutable references in the loop and I can't because I borroed an immutable reference.
The problem is slightly different. what happens is that you can't walk this Rc<RefCell> tree, at least not interactively like this, because the "borrow" of such structures need to be keep while you are working with it. And your implementation releases the "borrow" after each loop.
But then if a borrow_mut() I get that value is a private field, so I'm
assuming I can't access any properties of the contained value if it is
a mutable reference?
Not really, what is happening here is that you are not calling the function RefCell::borrow_mut that returns a RefMut<Node>, you are in fact calling <Rc as BorrowMut>::borrow_mut that returns &mut RefMut<...>. And by accessing the value you are trying the access the private field value from RefCell, not Node.
Notice that in my implementation I explicitly called RefCell::borrow_mut, that fixes this issue.
I'd implementing a simple linked list. This is the (working) code I had so far:
pub struct LinkedList<T> {
start: Option<Box<Link<T>>>,
}
impl<T> LinkedList<T> {
pub fn new() -> LinkedList<T> {
return LinkedList { start: None };
}
}
struct Link<T> {
value: Box<T>,
next: Option<Box<Link<T>>>,
}
impl<T> Link<T> {
fn new_end(value: T) -> Link<T> {
return Link::new(value, None);
}
fn new(value: T, next: Option<Box<Link<T>>>) -> Link<T> {
return Link {
value: Box::new(value),
next,
};
}
}
Next on the list is a method to append to the list; this is what I came up with:
pub fn append(&mut self, element: T) {
// Create the link to append
let new_link = Some(Box::new(Link::new_end(element)));
// Find the last element of the list. None, if the list is empty
let mut last = &self.start;
while let Some(link) = last {
last = &link.next;
}
// Insert the new link at the correct position
match last {
None => self.start = new_link,
Some(last) => last.next = new_link, // This fails
}
}
The precise compiler error is
error[E0594]: cannot assign to `last.next` which is behind a `&` reference
I vaguely get the problem; you cannot mutate an immutable reference. But making the references mutable does seem to make the errors even worse.
How does one handle these kinds of errors? Is there a simple quick-fix, or do you structure your code completely different in Rust?
Your code almost worked. It will if you bind mutably:
impl<T> LinkedList<T> {
pub fn append(&mut self, element: T) {
// Create the link to append
let new_link = Some(Box::new(Link::new_end(element)));
// Find the last element of the list. None, if the list is empty
let mut last = &mut self.start;
while let Some(link) = last {
last = &mut link.next;
}
// Insert the new link at the correct position
match last {
None => self.start = new_link,
Some(ref mut last) => last.next = new_link,
}
}
}
FYI, the answer to this recent question is very good at clarifying the matter about mutability, type and binding in Rust.
Here's the code (I also put it in a playpen here: http://is.gd/f9O3YG):
use std::mem;
pub struct Tree {
children: Vec<Option<Box<Tree>>>,
// other fields
}
impl Tree {
pub fn mutate(&mut self, x: i64) {
if self.is_base_case() {
// base case
unimplemented!();
} else {
// recursive case
let idx: usize = unimplemented!();
let mut subtree: Option<&mut Box<Tree>> = self.children.get_mut(idx).expect("child idx out of bounds").as_mut();
match subtree {
Some(ref mut subtree) => unimplemented!(),
None => {
let mut new_tree = Tree::new();
// recurse on the new tree here
mem::replace(&mut subtree, Some(&mut Box::new(new_tree)));
},
}
}
}
pub fn new() -> Tree {
unimplemented!();
}
fn is_base_case(&self) -> bool {
unimplemented!();
}
}
fn main() {
println!("it compiled!");
}
I'm writing a data structure which is a type of tree. It stores its subtrees in a Vec<Option<Box<Tree>>>, since it's not guaranteed to have a subtree in every position. I'm trying to write a method which mutates the tree, possibly creating one of the subtrees if it doesn't exist.
As you can see if you try to run the code in the playpen, my approach doesn't work. I'm not sure what the error message is telling me - my best guess is that it wants the newly created subtree to have the same lifetime as the subtree created on line 14, in order for the replacement to be safe. However, I'm not sure how to make it have that lifetime. It also made me think: since the new subtree will also need to be valid for the entire lifetime of the data structure, shouldn't it have the same lifetime as the parent tree? It might need to be shorter though, since there are other methods which can remove subtrees (I'm using Option::take for that, which works well enough - I checked the documentation for an opposite of that and couldn't find one). Is my approach flawed, and if not, how should I fix my implementation?
You're trying to put an &mut inside some structure which lives longer than the thing &mut is pointing to. Here's a reduced example:
use std::mem;
pub struct Tree {
children: Vec<Option<Box<Tree>>>,
}
impl Tree {
pub fn mutate(&mut self, x: i64) {
let idx: usize = unimplemented!();
let mut subtree: Option<&mut Box<Tree>> =
self.children.get_mut(idx).unwrap().as_mut();
let mut new_tree = Tree::new();
mem::replace(&mut subtree, Some(&mut Box::new(new_tree)));
}
pub fn new() -> Tree {
unimplemented!();
}
}
fn main() {}
The problem is that &mut Box::new(...) is a temporary reference, so you can't just copy it into another structure. Your use of as_mut on the Option is confusing; if you just don't do it your code works fine:
let mut subtree: &mut Option<Box<Tree>> =
self.children.get_mut(idx).unwrap();
let mut new_tree = Tree::new();
mem::replace(subtree, Some(Box::new(new_tree)));
Here's it in the larger context. You can simplify it a bit, too.
I have a struct container of Children and a method pop() that removes the last added Child and returns it's a value:
struct Child {
a: i32,
b: String,
}
struct Container<'a> {
vector: &'a mut Vec<Child>,
}
impl<'a> Container<'a> {
fn pop(&mut self) -> i32 {
return self.vector.pop().a;
}
}
I get the error during compilation:
error: no field `a` on type `std::option::Option<Child>`
--> src/main.rs:12:34
|
12 | return self.vector.pop().a;
| ^
Does the scope of Container's pop() not allow access to values of its Children's scope?
Vec::pop returns an Option<Child>, not a Child. This allows it to have something reasonable to return in case there are no elements in the Vec to pop off. To get at the a that may be inside, you can convert from Option<Child> to Child using unwrap(), but that will cause your program to panic if the Vec was empty. The code for that would look like this:
fn pop(&mut self) -> i32 {
return self.vector.pop().unwrap().a;
}
Another option would be to more closely copy Vec's behavior, and return None in case there are no elements. You could do that using Option's map method:
fn pop(&mut self) -> Option<i32> {
return self.vector.pop().map(|child| child.a)
}
For reference, I'm using Rust 0.7.
I'm trying to create a stack implementation using an owned linked list and I'm running into trouble.
trait Stack<T> {
fn push(&mut self, item : T);
fn pop(&mut self) -> Option<T>;
}
enum Chain<T> {
Link(T, ~Chain<T>),
Break
}
impl<T> Stack<T> for ~Chain<T> {
fn push(&mut self, item : T) {
*self = ~Link(item, *self);
}
fn pop(&mut self) -> Option<T> {
None
}
}
When I try to rustc stack.rs I get the following error:
stack.rs:13:28: 13:34 error: cannot move out of dereference of & pointer
stack.rs:13 *self = ~Link(item, *self);
^~~~~~
I don't know how I could overcome this or what I could do differently to allow this. It seems like I should be able to create this data structure without using managed pointers, but I haven't seen a lot of documentation on this sort of thing.
Either assignment from self (which I think includes constructing a new thing out of it, as in the case of Link(item, *self) implies a move. This means that in the process of constructing the new Link that self becomes unusable, because:
"After a value has been moved, it can no longer be used from the source location and will not be destroyed there."
The Right Way™ is probably best documented by what's done in this example in the stdlib. It's a doubly linked list, and it is managed, but it's mutable, and I hope copy free. There's also list of useful container types, too.
I did manage to get this immutable version of your datastructure working, however.
trait Stack<T> {
fn push(self, item : T) -> Self;
fn pop(self) -> Option<(T, Self)>;
fn new() -> Self;
}
#[deriving(Eq, ToStr)]
enum Chain<T> {
Link(T, ~Chain<T>),
Break
}
impl<T> Stack<T> for Chain<T> {
fn push(self, item : T) -> Chain<T> {
Link(item, ~self)
}
fn pop(self) -> Option<(T, Chain<T>)> {
match self {
Link(item, ~new_self) => Some((item, new_self)),
Break => None
}
}
fn new() -> Chain<T> {
Break
}
}
fn main() {
let b : ~Chain<int> = ~Stack::new();
println(b.push(1).push(2).push(3).to_str());
}