I was implementing an LinkedList to learn about smart pointers. This is the structures:
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
struct Node<T> {
value: T,
next: Link<T>,
}
impl<T> Node<T> {
pub fn new(value: T) -> Rc<RefCell<Node<T>>> {
Rc::new(RefCell::new(Node { value, next: None }))
}
}
struct LinkedList<T> {
head: Link<T>,
}
While implementing the push method, I faced a problem with iteration over node.next and I could solve this by doing the iteration with a loop, like this thread.
And before I move on to the next method, I've tried to implement with while let, but doesn't work, and I don;t figure out why.
let mut curr = Rc::clone(head);
while let Some(ref boxed) = curr.borrow().next {
curr = Rc::clone(boxed);
}
// loop {
// let next = match curr.borrow().next {
// Some(ref boxed) => Rc::clone(boxed),
// None => break,
// };
// curr = next;
// }
curr.borrow_mut().next = Some(node);
The error occurs because the curr.borrow().next is dropped when go to the next iteration?
Is there a way to implement that with while let?
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.
I am writing a recursive type ListNode in Rust. I have to use Box in the struct and I am trying to write a loop to add next ListNode. However, I would like to try using a pointer except recursive method.
#[derive(Debug)]
struct ListNode {
val: i32,
next: Option<Box<ListNode>>,
}
impl ListNode {
fn new(i: i32) -> Self {
ListNode { val: i, next: None }
}
fn add_l(&mut self, l: &Vec<i32>) {
let mut p: *mut ListNode = self as *mut ListNode;
for i in l {
unsafe {
(*p).next = Some(Box::new(ListNode::new(*i)));
let temp_b = Box::from_raw(p);
p = Box::into_raw(temp_b.next.wrap());
};
}
}
}
fn main() {
let mut a = ListNode::new(1);
a.add_l(&vec![2, 3, 4, 5]);
println!("{:?}", a);
}
I found that a is changed to the last NodeList with the val of 5:
ListNode { val: 5, next: None }
Is there any way I can copy a pointer so I can keep a stable?
If there is no way I can copy pointer, how can I implement this?
First things first: using unsafe here is completely unnecessary and I would say actively malicious if I saw it in any real code. Don't use unsafe for "fun".
Here's a completely safe implementation of the function which walks backwards to construct the new tail of the list to add:
fn add_l(&mut self, l: &[i32]) {
let mut tail = None;
for &val in l.iter().rev() {
let next = tail.take();
tail = Some(Box::new(ListNode { val, next }));
}
self.next = tail;
}
And one that goes forwards, but requires an unwrap:
fn add_l(&mut self, l: &[i32]) {
let mut head = self;
for &val in l {
head.next = Some(Box::new(ListNode::new(val)));
head = { head }.next.as_mut().unwrap();
}
}
If you had to do it in the forwards direction and had to avoid the unwrap, then maybe you could use unsafe. Every single unsafe block should contain a wealth of comments explaining how the code is safe and doesn't break the guarantees that you need to uphold.
fn add_l(&mut self, l: &[i32]) {
let mut head = self;
for &val in l {
unsafe {
// Boxing a value gives it a stable address.
let mut node = Box::new(ListNode::new(val));
// So long as this raw pointer doesn't escape this block,
// we don't need to worry about its lifetime as it should
// outlive what we need.
let node_raw = &mut node as &mut ListNode as *mut ListNode;
head.next = Some(node);
// Now that we've moved the `Box` into its final place,
// we throw away the reference to head to avoid mutable
// aliasing
head = &mut *node_raw;
}
}
}
See also:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec) or Box (&Box) as a function argument?
Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time
You have a number of issues here, none of which relate to copying a pointer.
I see what you're trying to do, but you're seeing 'undefined behavior' in action, not a failure to copy the pointer value.
First of all, this:
temp_b.next.unwrap()
Unwrap does not leave the object behind; it consumes it. Every iteration through, you will be setting the value of next to nothing as you call unwrap.
Secondly, on the first iteration through your loop, you convert the original pointer into a box:
let mut p: *mut ListNode = self as *mut ListNode;
// ... p is not reassigned before calling the next statement
Box::from_raw(p);
As a result, you're dropping (free'ing) the root object a when you consume temp_b.
This won't immediately trigger a crash, but it means you've now effectively corrupted the stack. Everything past this point is undefined behavior.
Look at the output when you trace your actual pointer values:
#[derive(Debug)]
struct ListNode {
val: String,
next: Option<Box<ListNode>>,
}
impl ListNode {
fn new(i: &str) -> Self {
ListNode { val: format!("{:?}", i), next: None }
}
fn add_l(&mut self, l: &Vec<&str>) {
let mut p: *mut ListNode = self as *mut ListNode;
println!("self -> {:?}", self as *mut ListNode);
for i in l {
unsafe {
(*p).next = Some(Box::new(ListNode::new(*i)));
let temp_b = Box::from_raw(p);
println!("{:?} -> {:?}", p, temp_b);
p = Box::into_raw(temp_b.next.unwrap());
println!("next p -> {:?}", p);
};
}
println!("self -> {:?}", self as *mut ListNode);
}
}
fn main() {
let mut a = ListNode::new("1");
a.add_l(&vec!["2", "3", "4", "5"]);
println!("self -> {:?}", &mut a as *mut ListNode);
println!("{:?}", a);
}
...
self -> 0x7ffdc10a90f0
0x7ffdc10a90f0 -> ListNode { val: "\"1\"", next: Some(ListNode { val: "\"2\"", next: None }) }
next p -> 0x7fdde801f060
0x7fdde801f060 -> ListNode { val: "\"2\"", next: Some(ListNode { val: "\"3\"", next: None }) }
next p -> 0x7ffdc10a90f0
0x7ffdc10a90f0 -> ListNode { val: "\"3\"", next: Some(ListNode { val: "\"4\"", next: None }) }
next p -> 0x7fdde801f060
0x7fdde801f060 -> ListNode { val: "\"4\"", next: Some(ListNode { val: "\"5\"", next: None }) }
next p -> 0x7ffdc10a90f0 <---- Whhhaaaat! You've been reallocated!
self -> 0x7ffdc10a90f0
self -> 0x7ffdc10a90f0
ListNode { val: "\"5\"", next: None }
So... this is why using unsafe is unsafe.
You can't do what you want to do without using raw pointers all the way; I recommend you look at Rc for what you're trying to do.
I'm trying to implement a dequeue function for a queue but I am confused how the borrow checker works. What am I doing wrong in this code?
use std::cell::RefCell;
use std::rc::Rc;
use std::mem::replace;
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
struct Node<T>{
item: T,
next: Link<T>
}
pub struct Queue<T>{
first: Link<T>,
last: Link<T>,
length: usize
}
impl<T> Queue<T>{
pub fn new() -> Queue<T> {
Queue {
first: None,
last: None,
length: 0
}
}
pub fn is_empty(&self) -> bool {
self.length == 0
}
pub fn size(&self) -> usize {
self.length
}
pub fn enqueue(&mut self, item: T) {
let temp = self.last.take();
self.last = Some(Rc::new(RefCell::new(Node{
item,
next: None
})));
if self.is_empty() {
self.first = self.last.clone();
} else {
let temp = temp.unwrap();
temp.borrow_mut().next = self.last.clone();
}
self.length += 1;
}
pub fn dequeue(&mut self) -> Result<T, String>{
if let Some(ref mut value) = self.first.take() {
let mut temp = *(value.borrow_mut());
let next = *(temp.next.unwrap().borrow_mut());
let old_value = replace(&mut temp, next);
return Ok(old_value.item);
}
Err("Queue is empty".to_owned())
}
}
Having obtained a mutable reference to the value inside Some, I want to replace with the node that is being referenced by the next field of the node. Do I need to take ownership of the value inside Some? Can I even do that?
Here is an implementation of the dequeue:
pub fn dequeue(&mut self) -> Result<T, String> {
// First, disconnect `self.last` from the element it is pointing,
// since it will have to be updated anyway. If there is no elemen in the
// queue, we're done.
let first = try!(self.first.take().ok_or("Queue is empty".to_owned()));
// if there are two Rc's pointing to this node, then this must be the
// only node, so `self.last` has to go
if Rc::strong_count(&first) == 2 {
self.last = None;
}
let first_node = Rc::try_unwrap(first).ok().expect(
"This should be the only owner of the node"
).into_inner();
self.first = first_node.next;
self.length -= 1;
Ok(first_node.item)
}
Here is the complete code. I also added a dequeue_back for making this almost a double ended queue and some tests.
Here is my code:
struct Node<T> {
data: T,
next: Option<Box<Node<T>>>,
}
impl<T> Node<T> {
fn new(data : T) -> Node<T> {
Node { data: data, next: None }
}
fn new_with_next(data: T, next: Option<Box<Node<T>>>) -> Node<T> {
Node { data: data, next: next }
}
}
struct LinkedList<T> {
head: Box<Node<T>>,
size: u8,
}
impl<T> LinkedList<T> {
fn new(data: T) -> LinkedList<T> {
let new_node = Node::new(data);
let head = Box::new(new_node);
LinkedList { head: head, size: 1 }
}
fn insert(&mut self, data: T) {
let mut next = Some(self.head); // <-- error here
let new_node = Node::new_with_next(data, next);
self.head = Box::new(new_node);
self.size += 1;
}
}
I get this error:
src\linked_list.rs:28:29: 28:33 error: cannot move out of borrowed content [E0507]
src\linked_list.rs:28 let next = Some(self.head);
^~~~
I don't understand the error, nor how to fix it. I tried giving a reference to self.head to Some, however I'm changing the data type this inside Some this way.
The problem is that you take self by reference, therefore you cannot move out its head (it would become invalid), which let mut next = Some(self.head); would do.
std::mem::replace is a nice function for this:
fn insert(&mut self, data: T) {
let mut next = std::mem::replace(&mut self.head, Box::new(Node::new(data)));
self.head.next = Some(next);
self.size += 1;
}
It allows you to replace the head with a new node and get the old one at the same time, which Rust is happy about because head stays valid all along now.