Multiple mutable borrows during a depth-first tree search - rust

How would one restructure this function that does a depth-first search and returns the parent of the matching node?
I know that variations of this problem have come up very often (e.g. Multiple mutable borrows when generating a tree structure with a recursive function in Rust, Mut borrow not ending where expected), but I still can’t figure out how to modify it to work. I have tried variations using slices, std::mem::drop, and adding lifetime parameters where 'a: 'b but I still haven’t figured out write it without conditionally mutably borrowing a variable in one branch and then using the variable in another branch.
#[derive(Clone, Debug)]
struct TreeNode {
id: i32,
children: Vec<TreeNode>,
}
// Returns a mutable reference to the parent of the node that matches the given id.
fn find_parent_mut<'a>(root: &'a mut TreeNode, id: i32) -> Option<&'a mut TreeNode> {
for child in root.children.iter_mut() {
if child.id == id {
return Some(root);
} else {
let descendent_result = find_parent_mut(child, id);
if descendent_result.is_some() {
return descendent_result;
}
}
}
None
}
fn main() {
let mut tree = TreeNode {
id: 1,
children: vec![TreeNode {
id: 2,
children: vec![TreeNode {
id: 3,
children: vec![],
}],
}],
};
let a: Option<&mut TreeNode> = find_parent_mut(&mut tree, 3);
assert_eq!(a.unwrap().id, 2);
}
error[E0499]: cannot borrow `*root` as mutable more than once at a time
--> src/main.rs:11:25
|
9 | for child in root.children.iter_mut() {
| ------------- first mutable borrow occurs here
10 | if child.id == id {
11 | return Some(root);
| ^^^^ second mutable borrow occurs here
...
20 | }
| - first borrow ends here
Here it is with #huon’s suggestions and continued compiler errors:
fn find_parent_mut<'a>(root: &'a mut TreeNode, id: i32) -> Option<&'a mut TreeNode> {
for child in root.children {
if child.id == id {
return Some(root);
}
}
for i in 0..root.children.len() {
let child: &'a mut TreeNode = &mut root.children[i];
let descendent_result = find_parent_mut(child, id);
if descendent_result.is_some() {
return descendent_result;
}
}
None
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:9:18
|
9 | for child in root.children {
| ^^^^ cannot move out of borrowed content
error[E0499]: cannot borrow `root.children` as mutable more than once at a time
--> src/main.rs:15:44
|
15 | let child: &'a mut TreeNode = &mut root.children[i];
| ^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first mutable borrow occurs here
...
22 | }
| - first borrow ends here

I managed to have it working this way:
fn find_parent_mut<'a>(root: &'a mut TreeNode, id: i32)
-> Option<&'a mut TreeNode> {
if root.children.iter().any(|child| {child.id == id}) {
return Some(root);
}
for child in &mut root.children {
match find_parent_mut(child, id) {
Some(result) => return Some(result),
None => {}
}
}
None
}
First in you second attempt, you wrote for child in root.children instead of the for child in &mut root.children (note the missing &mut),which caused root.children to be consumed by the loop instead of just iterated over, hence the cannot move out of borrowed content error.
I also folded it in a more iterator-ich way, using the any(..) function.
For the second loop, I'm not exactly sure what was going on, by apparently binding the references to variables was confusing the borrow-checker. I removed any temporary variable, and now it compiles.

One can do this in a single pass by doing the search, recording some data from it, and then computing the return value efficiently outside the loop:
let mut found = Err(());
for (i, child) in root.children.iter_mut().enumerate() {
if child.id == id {
found = Ok(None);
break;
} else find_parent_mut(child, id).is_some() {
found = Ok(Some(i));
break;
}
}
match found {
Ok(Some(i)) => Some(&mut root.children[i]),
Ok(None) => Some(root),
Err(()) => None,
}
This avoids the issues caused by conditionally returning mutable variables (which is the problems you and my answer below were meeting) by completely avoiding returns inside the inner loop.
Old/incorrect answer:
I'm unable to test my suggestions right now, but I believe the best way to solve this is to return root outside the loop.
for child in &mut root.children {
if child.id == id {
found = true;
break
} ...
}
if found {
Some(root)
} else {
None
}
This (hopefully) ensures that root isn't borrowed via children when it is being manipulated.
However I suspect the early return inside the main loop may interfere, in which case one might just have to fall back to integers and indexing:
for i in 0..root.children.len() {
if root.children[i].id == id {
return Some(root)
...
}

Related

Linked list. Can't change borrowed value

I am on my way of learning Rust. In practical purpose I decided to make my own linked list collection. But I faced with some problems soon. I tried but can't find any way to fix this problem. Can I do this using this type of structure for linked list? The main problem I faced is implementation of deleting function.This function should delete element from the list with replacing address of the current node with address of the next node. But I can't change the value because it was borrowed already.
#[derive(Debug, PartialEq)]
enum AlmostList {
Cons(i32, Box<AlmostList>),
Nil,
}
The base of linked list is enumeration.
#[derive(Debug, PartialEq)]
struct List {
length: u32,
data: AlmostList,
}
But I want the instance of list knows its own length. Because of it I decided to use structure to store the length of the list in it.
use crate::AlmostList::{Cons, Nil};
//Implementetion of functions
impl List {
fn new() -> List {
List{ length: 0_u32, data: AlmostList::Nil }
}
fn append(&mut self, elem: i32) {
let mut alist = &mut self.data;
loop {
match alist {
Cons(_, ref mut ptr) => alist = ptr,
Nil => {
let node = Cons(elem, Box::new(Nil));
self.length += 1;
*alist = node;
break;
},
}
}
}
fn show(&self) {
let mut alist = &self.data;
if let Nil = alist {
panic!("List is empty");
}
loop {
match alist {
Cons(value, ptr) => {
print!("{} ", value);
alist = &*ptr;
},
Nil => break,
}
}
}
}
Everything was fine until I started to write function of deleting elements.This function should delete element from the list with replacing address of the current node with address of the next node.
fn delete(&mut self, number: i32) -> Option<i32> {
let mut alist = &mut self.data;
let result = loop {
match alist {
Cons(value, ptr) => {
if *value != number {
alist = ptr;
}
self.length -= 1;
*alist = *ptr.clone();
break Some(number);
},
Nil => break None,
}
};
result
}
}
Got this error:
error[E0506]: cannot assign to `*alist` because it is borrowed
--> main.rs:79:25
|
73 | Cons(value, ptr) => {
| --- borrow of `*alist` occurs here
...
79 | *alist = *ptr.clone();
| ^^^^^^
| |
| assignment to borrowed `*alist` occurs here
| borrow later used here
error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as mutable
--> main.rs:79:35
|
75 | alist = ptr;
| --- mutable borrow occurs here
...
79 | *alist = *ptr.clone();
| ------ ^^^ immutable borrow occurs here
| |
| mutable borrow later used here
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0502, E0506.
For more information about an error, try `rustc --explain E0502`.
Can I solve this problem somehow?
Yes, you can solve this problem. I fixed it in that way:
pub fn delete(&mut self, number: i32) -> Option<i32> {
let mut alist = &mut self.data;
let result = loop {
match alist {
AlmostList::Cons(value, ref mut ptr) => {
if *value != number {
alist = ptr;
} else {
break Some(ptr);
}
}
AlmostList::Nil => break None,
}
};
if let Some(ptr) = result {
*ptr = Box::new(AlmostList::Nil);
Some(number)
} else {
None
}
}
At least the code above was compiled successfully. Full rust playground example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5bd28014bdec30e5c2e851827f15dad5
Additional hints:
write better namings. Examples: AlmostLeast -> ListNode (or just Node), Nil -> None, Cons -> Some. I have feeling that you have experience with Lisp in the past :)
format your code with cargo fmt and check with cargo clippy
any data structure implementations should not panic. Use Result type
Update:
Code above is wrong. I've implemented it using recursion: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ea6dbd3a627a59014df823be29e296b2

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...

Mutably borrowing in match statement and result

I'm trying to determine if a container has an object and return the found object if it does, or add it if it doesn't.
I've found Rust borrow mutable self inside match expression
which has an answer which says what I am trying to do can't (couldn't?) be done.
In my situation, I've got some objects that have vectors of children. I don't want to expose the internals of my object, because I may want to change the representation underneath.
How can you resolve the need to mutably borrow in different match arms in Rust? seems to suggest I may be able to do what I want if I get the lifetimes correct, but I haven't been able to figure out how.
Here's a representation of the issue I'm having:
fn find_val<'a>(container: &'a mut Vec<i32>, to_find: i32) -> Option<&'a mut i32> {
for item in container.iter_mut() {
if *item == to_find {
return Some(item);
}
}
None
}
fn main() {
let mut container = Vec::<i32>::new();
container.push(1);
container.push(2);
container.push(3);
let to_find = 4;
match find_val(&mut container, to_find) {
Some(x) => {
println!("Found {}", x);
}
_ => {
container.push(to_find);
println!("Added {}", to_find);
}
}
}
playground
The error I get is:
error[E0499]: cannot borrow `container` as mutable more than once at a time
--> src/main.rs:24:13
|
19 | match find_val(&mut container, to_find) {
| --------- first mutable borrow occurs here
...
24 | container.push(to_find);
| ^^^^^^^^^ second mutable borrow occurs here
...
27 | }
| - first borrow ends here
Put the change in a function, and use early return instead of an else branch:
fn find_val_or_insert(container: &mut Vec<i32>, to_find: i32) {
if let Some(x) = find_val(&container, to_find) {
println!("Found {}", x);
return; // <- return here instead of an else branch
}
container.push(to_find);
println!("Added {}", to_find);
}
See also Mutable borrow more than once and How to update-or-insert on a Vec?

Iterating through a recursive structure using mutable references and returning the last valid reference

I'm trying to recurse down a structure of nodes, modifying them, and then returning the last Node that I get to. I solved the problems with mutable references in the loop using an example in the non-lexical lifetimes RFC. If I try to return the mutable reference to the last Node, I get a use of moved value error:
#[derive(Debug)]
struct Node {
children: Vec<Node>,
}
impl Node {
fn new(children: Vec<Self>) -> Self {
Self { children }
}
fn get_last(&mut self) -> Option<&mut Node> {
self.children.last_mut()
}
}
fn main() {
let mut root = Node::new(vec![Node::new(vec![])]);
let current = &mut root;
println!("Final: {:?}", get_last(current));
}
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
let temp = current;
println!("{:?}", temp);
match temp.get_last() {
Some(child) => { current = child },
None => break,
}
}
current
}
Gives this error
error[E0382]: use of moved value: `*current`
--> test.rs:51:5
|
40 | let temp = current;
| ---- value moved here
...
51 | current
| ^^^^^^^ value used here after move
|
= note: move occurs because `current` has type `&mut Node`, which does not implement the `Copy` trait
If I return the temporary value instead of breaking, I get the error cannot borrow as mutable more than once.
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
let temp = current;
println!("{:?}", temp);
match temp.get_last() {
Some(child) => { current = child },
None => return temp,
}
}
}
error[E0499]: cannot borrow `*temp` as mutable more than once at a time
--> test.rs:47:28
|
43 | match temp.get_last() {
| ---- first mutable borrow occurs here
...
47 | None => return temp,
| ^^^^ second mutable borrow occurs here
48 | }
49 | }
| - first borrow ends here
How can I iterate through the structure with mutable references and return the last Node? I've searched, but I haven't found any solutions for this specific problem.
I can't use Obtaining a mutable reference by iterating a recursive structure because it gives me a borrowing more than once error:
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
let temp = current;
println!("{:?}", temp);
match temp.get_last() {
Some(child) => current = child,
None => current = temp,
}
}
current
}
This is indeed different from Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If we look at the answer there, modified a bit, we can see that it matches on a value and is able to return the value that was matched on in the terminal case. That is, the return value is an Option:
fn back(&mut self) -> &mut Option<Box<Node>> {
let mut anchor = &mut self.root;
loop {
match {anchor} {
&mut Some(ref mut node) => anchor = &mut node.next,
other => return other, // transferred ownership to here
}
}
}
Your case is complicated by two aspects:
The lack of non-lexical lifetimes.
The fact that you want to take a mutable reference and "give it up" in one case (there are children) and not in the other (no children). This is conceptually the same as this:
fn maybe_identity<T>(_: T) -> Option<T> { None }
fn main() {
let name = String::from("vivian");
match maybe_identity(name) {
Some(x) => println!("{}", x),
None => println!("{}", name),
}
}
The compiler cannot tell that the None case could (very theoretically) continue to use name.
The straight-forward solution is to encode this "get it back" action explicitly. We create an enum that returns the &mut self in the case of no children, a helper method that returns that enum, and rewrite the primary method to use the helper:
enum LastOrNot<'a> {
Last(&'a mut Node),
NotLast(&'a mut Node),
}
impl Node {
fn get_last_or_self(&mut self) -> LastOrNot<'_> {
match self.children.is_empty() {
false => LastOrNot::Last(self.children.last_mut().unwrap()),
true => LastOrNot::NotLast(self),
}
}
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
match { current }.get_last_or_self() {
LastOrNot::Last(child) => current = child,
LastOrNot::NotLast(end) => return end,
}
}
}
}
Note that we are using all of the techniques exposed in both Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in? and Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time.
With an in-progress reimplementation of NLL, we can simplify get_last_or_self a bit to avoid the boolean:
fn get_last_or_self(&mut self) -> LastOrNot<'_> {
match self.children.last_mut() {
Some(l) => LastOrNot::Last(l),
None => LastOrNot::NotLast(self),
}
}
The final version of Polonius should allow reducing the entire problem to a very simple form:
fn get_last(mut current: &mut Node) -> &mut Node {
while let Some(child) = current.get_last() {
current = child;
}
current
}
See also:
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time

Rust lifetime issue in loop

How to get this example to compile without array copying or multiple calls to b() per iteration — b() has to perform some expensive parsing?
This is not the full code that I wrote, but it illustrates the problem I had. Here, Test is attempting to perform some kind of streaming parsing work. c() is the parsing function, it returns Some when parsing was successful. b() is a function that attempts to read more data from the stream when c() can not parse using the available data yet. The returned value is a slice into the self.v containing the parsed range.
struct Test {
v: [u8; 10],
index: u8,
}
impl Test {
fn b(&mut self) {
self.index = 1
}
fn c(i: &[u8]) -> Option<&[u8]> {
Some(i)
}
fn a(&mut self) -> &[u8] {
loop {
self.b();
match Test::c(&self.v) {
Some(r) => return r,
_ => continue,
}
}
}
}
fn main() {
let mut q = Test {
v: [0; 10],
index: 0,
};
q.a();
}
When compiling, it produces the following borrow checker error:
error[E0502]: cannot borrow `*self` as mutable because `self.v` is also
borrowed as immutable
--> <anon>:17:13
|
17 | self.b();
| ^^^^ mutable borrow occurs here
18 |
19 | match Test::c(&self.v) {
| ------ immutable borrow occurs here
...
24 | }
| - immutable borrow ends here
If I change a() to:
fn a(&mut self) -> Option<&[u8]> {
loop {
self.b();
if let None = Test::c(&self.v) {
continue
}
if let Some(r) = Test::c(&self.v) {
return Some(r);
} else {
unreachable!();
}
}
}
Then it runs, but with the obvious drawback of calling the parsing function c() twice.
I kind of understand that changing self while the return value depends on it is unsafe, however, I do not understand why is the immutable borrow for self.v is still alive in the next iteration, when we attempted to call b() again.
Right now "Rustc can't "deal" with conditional borrowing returns". See this comment from Gankro on issue 21906.
It can't assign a correct lifetime to the borrow if only one execution path terminates the loop.
I can suggest this workaround, but I'm not sure it is optimal:
fn c(i: &[u8]) -> Option<(usize, usize)> {
Some((0, i.len()))
}
fn a(&mut self) -> &[u8] {
let parse_result;
loop {
self.b();
match Test::c(&self.v) {
Some(r) => {
parse_result = r;
break;
}
_ => {}
}
}
let (start, end) = parse_result;
&self.v[start..end]
}
You can construct result of parsing using array indexes and convert them into references outside of the loop.
Another option is to resort to unsafe to decouple lifetimes. I am not an expert in safe use of unsafe, so pay attention to comments of others.
fn a(&mut self) -> &[u8] {
loop {
self.b();
match Test::c(&self.v) {
Some(r) => return unsafe{
// should be safe. It decouples lifetime of
// &self.v and lifetime of returned value,
// while lifetime of returned value still
// cannot outlive self
::std::slice::from_raw_parts(r.as_ptr(), r.len())
},
_ => continue,
}
}
}

Resources