I am trying to create a linked list in Rust, and to append values in the end, I need to traverse it and then add this new value. Im avoiding recursion, as in large lists it would be bad, plus trying to understand the Box logic better.
The problem is, after traversing, my variable 'current' is a mutable reference to the last node of the list. But I cant modify it, Rust complains about references that are already dropped at this scope.
struct Node {
valor: Option<String>,
next: Option<Box<Node>>,
}
impl Node {
fn new(valor: Option<String>) -> Node {
Node { valor, next: None }
}
}
struct NodeList {
head: Option<Box<Node>>,
}
impl NodeList {
fn new() -> NodeList {
NodeList { head: None }
}
fn append(&mut self, novo: Node) {
if self.head.is_none() {
self.head = Some(Box::new(novo));
} else {
let mut current: &mut Option<Box<Node>> = &mut self.head;
loop {
let after: &mut Option<Box<Node>> = &mut (current.as_mut().unwrap()).next;
if after.is_none() {
break;
} else {
current = after;
}
}
current.as_mut().unwrap().next = Some(Box::new(novo));
}
}
}
fn main() {
let mut lista = NodeList::new();
for c in "açafrão".chars() {
let s = String::from(c);
lista.append(Node::new(Some(s)));
}
}
The error message:
error[E0499]: cannot borrow `*current` as mutable more than once at a time
--> src\main.rs:32:13
|
25 | let after: &mut Option<Box<Node>> = &mut (current.as_mut().unwrap()).next;
| ---------------- first mutable borrow occurs here
...
32 | current.as_mut().unwrap().next = Some(Box::new(novo));
| ^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
What am I doing wrong and how can I solve the issue?
In think in your special case you ran into an unsolved corner case of the borrow checker. Your code will compile in the future, but currently doesn't.
More info about this can be seen here: https://docs.rs/polonius-the-crab/
To demonstrate that this is in fact the case, your code builds and works fine with the experimental (and not yet stable) polonius borrow checker:
RUSTFLAGS="-Zpolonius" cargo +nightly run
The best way to fix this in your case is to rearrange the order of the calls so the compiler understands them better, like this:
#[derive(Debug)]
struct Node {
valor: Option<String>,
next: Option<Box<Node>>,
}
impl Node {
fn new(valor: Option<String>) -> Node {
Node { valor, next: None }
}
}
#[derive(Debug)]
struct NodeList {
head: Option<Box<Node>>,
}
impl NodeList {
fn new() -> NodeList {
NodeList { head: None }
}
fn append(&mut self, novo: Node) {
if self.head.is_none() {
self.head = Some(Box::new(novo));
} else {
let mut current: &mut Node = &mut self.head.as_mut().unwrap();
loop {
if current.next.is_none() {
current.next = Some(Box::new(novo));
break;
}
current = current.next.as_mut().unwrap().as_mut();
}
}
}
}
fn main() {
let mut lista = NodeList::new();
for c in "açafrão".chars() {
let s = String::from(c);
lista.append(Node::new(Some(s)));
}
println!("{:#?}", lista);
}
NodeList { head: Some(Node { valor: Some("a"), next: Some(Node { valor: Some("ç"), next: Some(Node { valor: Some("a"), next: Some(Node { valor: Some("f"), next: Some(Node { valor: Some("r"), next: Some(Node { valor: Some("ã"), next: Some(Node { valor: Some("o"), next: None }) }) }) }) }) }) }) }
Side note:
Don't try to learn Rust by implementing a linked list. Linked lists are highly incompatible with Rusts ownership model.
If you insist on doing it anyway, this article is absolutely mandatory for guidance:
https://rust-unofficial.github.io/too-many-lists/
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'm trying to learn rust making a game with SDL2. I have a struct GameEngine which has ownership of some variables to control the game state.
The method GameEngine::run() is responsible to manage the game loop. I want this method to do 2 things:
Check if some event is related to closing the game and in this case break the loop
For any other kind of event I want to call a method GameEngine::handle_event() to handle it
The problem is that the compiler is refusing to accept my code telling me I'm trying to borrow self as mutable more than once. The first borrow happen on this line:
let event_poll_iterator = self.event_pump.poll_iter();
and the second on this:
self.handle_event(event);
As I'm a newbie in Rust, I'm getting stuck in this error.
The complete code:
pub mod engine {
use std::time::Duration;
use sdl2::{EventPump, Sdl};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::render::WindowCanvas;
fn get_canvas(sdl_context: &Sdl) -> WindowCanvas {
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem
.window("SDL2 Snake Game", 800, 600)
.position_centered()
.opengl()
.build()
.map_err(|e| e.to_string()).unwrap();
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string()).unwrap();
canvas.set_draw_color(Color::BLACK);
canvas
}
pub struct GameEngine {
context: Sdl,
event_pump: EventPump,
canvas: WindowCanvas,
}
impl GameEngine {
pub fn new() -> Self {
let context = sdl2::init().unwrap();
let canvas = get_canvas(&context);
let event_pump = context.event_pump().unwrap();
GameEngine { context, canvas, event_pump }
}
fn redraw(&mut self) {
self.canvas.clear();
self.canvas.present();
}
fn handle_event(&mut self, event: Event) {
todo!()
}
pub fn run(&mut self) {
'game_loop: loop {
let event_poll_iterator = self.event_pump.poll_iter();
for event in event_poll_iterator {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'game_loop,
_ => {
self.handle_event(event);
}
}
}
self.redraw();
std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 30));
}
}
}
}
Edit
I could reproduce the same problem (I think) with a much smaller example:
struct List {
v: Vec<u32>
}
impl List {
fn increment(&mut self, x: &mut u32) {
*x += 1;
}
fn iter(&mut self) {
for x in &mut self.v {
self.increment(x);
}
}
}
fn main() {
let mut list = List { v: vec![1, 2, 3] };
list.iter();
assert!(list.v == vec![2, 3, 4]);
}
Error log:
λ cargo run
Compiling rustlings v4.7.1 (/home/luizalabs/repositories/rust/rustlings)
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:12:13
|
11 | for x in &mut self.v {
| -----------
| |
| first mutable borrow occurs here
| first borrow later used here
12 | self.increment(x);
| ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `rustlings` due to previous error
The problem is, self.handle_event could modify whatever you are iterating over (in this case event_poll_iterator). If you are modifying what the iterator is iterating over, you might want to consider cloning the iterator. If self.handle_event isn't modifying the iterator, you have to show the borrow checker that you are not modifying the iterator. One option is to inline self.handle_event. Another option is to pass whatever you are modifying as mutable to self.handle_event. Here is a simple example of what is going on:
#[derive(Debug)]
struct Point {
x: i32,
y: i32
}
struct Points {
points: Vec<Point>,
num_points: usize
}
impl Points {
fn bar(&mut self, point: &mut Point) {
println!("{:?}", point)
}
fn foo(&mut self) {
for p in &mut self.points {
self.bar(p);
}
}
}
Inlining would change foo as such:
fn foo(&mut self) {
for p in &mut self.points {
println!("{:?}", p); // modified line
}
}
Tried to simplify your example
fn main() {
let i: i32 = 4326;
let b = i.to_le_bytes();
for i in 0..4 {
println!("{}", b[i]);
}
}
pub struct GameEngine {
event_pump: EventPump,
}
pub struct EventPump {
}
impl EventPump {
pub fn poll_iter(&mut self) -> Vec<i32> {
vec![0, 1, 2]
}
}
impl GameEngine {
pub fn new() -> Self {
GameEngine {
event_pump: EventPump { },
}
}
fn redraw(&mut self) {
}
fn handle_event(&mut self, _event: i32) {
todo!()
}
pub fn run(&mut self) {
loop {
let ep = self.event_pump.poll_iter();
let event_poll_iterator = ep.iter();
for event in event_poll_iterator {
match event {
_ => {
self.handle_event(*event);
}
}
}
self.redraw();
}
}
}
Hope without losing sense. Seems it compiled ok.
It changes Iter to vector instance but I'm not sure if that matters.
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?
I created a library to deal with digraphs: nodes that link (reference counted) to zero or one other nodes (as in linked lists, but in a digraph a node can be linked to by more than one node).
I am trying to use my library to create a list with a current node:
struct ListWithPointer<'a> {
pub nodes: DigraphNodeRef<String>,
pub current_node: Option<&'a mut DigraphNodeRef<String>>,
}
current_node points to a link in the list.
Now I am trying to move current node to the next element of the list (or to the beginning if the list ended):
fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
if this.current_node.is_some() {
this.current_node.iter_mut().for_each(|a| {
(*a).as_rc_mut().iter_mut()
.for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
});
} else {
this.current_node = Some(&mut this.nodes);
}
}
but whatever I do, it fails with an error like:
error[E0500]: closure requires unique access to `this.current_node` but it is already borrowed
--> src/lib.rs:150:51
|
148 | fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
| -- lifetime `'a` defined here
149 | if this.current_node.is_some() {
150 | this.current_node.iter_mut().for_each(|a| {
| ---------------------------- ^^^ closure construction occurs here
| |
| borrow occurs here
| argument requires that `this.current_node` is borrowed for `'a`
151 | (*a).as_rc_mut().iter_mut()
152 | .for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
| ----------------- second borrow occurs due to use of `this.current_node` in closure
Help to rewrite without errors.
Here is the library code:
use std::sync::Arc;
#[derive(Clone)]
pub struct DigraphNode<T> {
pub next: DigraphNodeRef<T>, // I made it `pub` to be able `item.next.next()` to remove an item from the middle.
data: T,
}
impl<T> DigraphNode<T> {
fn new(next: DigraphNodeRef<T>, data: T) -> Self {
Self { next, data }
}
}
pub struct DigraphNodeRef<T> {
rc: Option<Arc<DigraphNode<T>>>,
}
impl<T> DigraphNodeRef<T> {
pub fn new() -> Self {
Self {
rc: None
}
}
pub fn from_node(value: DigraphNode<T>) -> Self {
Self::from(Some(Arc::new(value)))
}
pub fn from(rc: Option<Arc<DigraphNode<T>>>) -> Self {
Self {
rc
}
}
pub fn as_rc(&self) -> &Option<Arc<DigraphNode<T>>> {
&self.rc
}
pub fn as_rc_mut(&mut self) -> &mut Option<Arc<DigraphNode<T>>> {
&mut self.rc
}
pub fn is_none(&self) -> bool {
self.rc.is_none()
}
pub fn remove(&mut self) -> bool {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
true
} else {
false
}
}
pub fn prepend(&mut self, value: T) -> Self {
let new_node = DigraphNode::new(self.clone(), value);
let new_node_ref = DigraphNodeRef::from_node(new_node);
*self = new_node_ref.clone();
new_node_ref
}
pub fn node(&self) -> Option<DigraphNode<T>>
where T: Clone
{
self.rc.clone().map(|node| (*node).clone())
}
/// TODO: Should return a reference.
pub fn data(&self) -> Option<T>
where T: Clone
{
self.rc.clone().map(|node| (*node).data.clone())
}
pub fn values(self) -> DigraphNodeValuesIterator<T> {
DigraphNodeValuesIterator {
underlying: self.clone()
}
}
}
impl<T> Clone for DigraphNodeRef<T> {
fn clone(&self) -> Self {
Self { rc: self.rc.clone() }
}
}
impl<T> Iterator for DigraphNodeRef<T> {
type Item = Arc<DigraphNode<T>>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
Some(rc.clone())
} else {
None
}
}
}
pub struct DigraphNodeValuesIterator<T> {
underlying: DigraphNodeRef<T>,
}
impl<T: Clone> Iterator for DigraphNodeValuesIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.underlying.next().map(|node| node.data.clone())
}
}
In Rust the mutable access is ensured to be exclusive, i.e. if you hold a reference, some other code can't grab a mutable reference.
Problem is this line:
this.current_node.iter_mut().for_each(...)
It grabs a mutable access to current_node, so it can't regain it again down the line.
Not to mention that iterating over Option is a strange decision.
If you want to move current_node to a different place, I'd try to reorganize your code such that reads are separate from writes, and they are performed in a sequence, instead of trying to do it in one go:
// detach the current_node for moving
if let Some(current_node_to_move) = this.current_node.take() {
let new_current_node_ref: &mut ... = ... // find new location logic
new_current_node_ref.replace(current_node_to_move);
} else {
...
}
Here in line 1 it does a write None update to current_node via this, but immediately relinquishes the mutable reference. Line 2 does a read (search), but also grabs a mutable reference to a new location. Line 3 writes to this location.
To get the linked list implementation right, I recommend https://rust-unofficial.github.io/too-many-lists/
When compiling the following code:
pub enum NodeType {
None,
Node(Box<Node>),
}
pub struct Node {
next: NodeType,
}
impl Node {
fn traverse_recursively<F>(&self, depth: usize, f: &mut F)
where
F: FnMut(&Node, usize),
{
f(self, depth);
match &self.next {
NodeType::None => {}
NodeType::Node(node) => {
node.traverse_recursively(depth + 1, f);
}
}
}
pub fn visit_all<F>(&self, f: &mut F)
where
F: FnMut(&Node, usize),
{
self.traverse_recursively(1, f);
}
}
pub fn create_small_recursive_structure() -> Node {
Node {
next: NodeType::Node(Box::new(Node {
next: NodeType::Node(Box::new(Node { next: NodeType::None })),
})),
}
}
#[test]
fn test_so() {
let parent = create_small_recursive_structure();
let mut visited = Vec::new();
parent.visit_all(&mut |node, depth| {
visited.push((node, depth));
});
}
The compiler gives me the following error:
error[E0521]: borrowed data escapes outside of closure
--> src/so_question.rs:50:9
|
47 | let mut visited = Vec::new();
| ----------- `visited` declared here, outside of the closure body
48 |
49 | parent.visit_all(&mut |node, depth| {
| ---- `node` is a reference that is only valid in the closure body
50 | visited.push((node, depth));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `node` escapes the closure body here
I have found a similar question here, but the solution does not help me. I.e. my closure parameters already has no types, and I've experimented by adding and removing types and it doesn't seem to help.
What would I need to do in order to temporarily store a vector of references to the nodes in the tree structure? The intention is for the vector to live shorter than the node structure. Adding an extra pair of brackets to emphasize this for the compiler doesn't help.
Thanks!
You need to specify the lifetimes, so the compiler knows that the references will live for the same amount as self does:
pub enum NodeType {
None,
Node(Box<Node>),
}
pub struct Node {
next: NodeType,
}
impl Node {
fn traverse_recursively<'s, F>(&'s self, depth: usize, f: &mut F)
where
F: FnMut(&'s Node, usize),
{
f(self, depth);
match &self.next {
NodeType::None => {}
NodeType::Node(node) => {
node.traverse_recursively(depth + 1, f);
}
}
}
pub fn visit_all<'s, F>(&'s self, f: &mut F)
where
F: FnMut(&'s Node, usize),
{
self.traverse_recursively(1, f);
}
}
pub fn create_small_recursive_structure() -> Node {
Node {
next: NodeType::Node(Box::new(Node {
next: NodeType::Node(Box::new(Node { next: NodeType::None })),
})),
}
}
#[test]
fn test_so() {
let parent = create_small_recursive_structure();
let mut visited = Vec::new();
parent.visit_all(&mut |node: &Node, depth| {
visited.push((node, depth));
});
}
Playground