Cannot move out of dereference of `&mut`-pointer when calling Option::unwrap - rust

The following code doesn't compile:
struct Node {
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}
impl Node {
fn new() -> Node {
Node { left: None, right: None, }
}
}
fn init_tree(root: &mut Box<Node>, n: int) {
match n {
0 => {},
_ => {
root.left = Some(box Node::new());
root.right = Some(box Node::new());
init_tree(&mut root.left.unwrap(), n - 1);
init_tree(&mut root.left.unwrap(), n - 1);
}
}
}
fn main() {
let mut root: Box<Node> = box Node::new();
init_tree(&mut root, 10);
}
The compiler error is
error: cannot move out of dereference of `&mut`-pointer
init_tree(&mut root.left.unwrap(), n - 1);
^~~~
How could I fix this error?

The Rust compiler makes no pretence to intellectual eminence or scholarship sublime; it does exactly what you tell it to, not what you meant or wanted.
In this case, when you say &mut root.left.unwrap(), what you are wanting is something that takes Option<Box<Node>> by mutable reference and gives you a &mut Box<Node>; but that’s definitely not what you actually told it to do.
What you told it to do was to take a mutable reference to the result of root.left.unwrap(); let’s look at the signature for Option.unwrap:
fn unwrap(self) -> T
So what root.left.unwrap() does is it consumes root.left, producing in its stead a Box<Node> object (or panicking if it was None). You are then left with the entire expression &mut root.left.unwrap() producing &mut Box<Node>, and consuming root.left and hence partially root. Now this you are definitely not permitted to do, as it would leave root needing to be destroyed, but you only had a mutable reference to it—it is not yours to destroy. Hence the error.
The solution is not to use unwrap but rather to write a suitable match expression yourself. Remember, .unwrap() is just match self { Some(x) => x, None => panic!(…) }, there’s nothing magic about it.
You’ll end up with something like this:
fn init_tree(root: &mut Node, n: int) {
if n != 0 {
root.left = Some(box Node::new());
root.right = Some(box Node::new());
init_tree(match root.left { Some(box ref mut x) => x, None => unreachable!() }, n - 1);
init_tree(match root.right { Some(box ref mut x) => x, None => unreachable!() }, n - 1);
}
}
(The box ref mut x part is a bit of a tangle, I’m afraid; it produces a &mut T from a Box<T>, the box meaning “unbox the value” and the ref mut meaning “and then take a mutable reference to it”. Remember that everything is back to front in patterns, with box and & meaning the opposite to what they do outside and with the whole lot reading left to right rather than right to left. Also, while you could work with &mut Box<Node> I would recommend using &mut Node there which removes one level of indirection. Incidentally if you were still using &mut Box<Node>, root.left.as_mut().unwrap() would work as well.)
This can be improved by not stuffing the thing into root immediately:
fn init_tree(root: &mut Node, n: int) {
if n != 0 {
let mut left = box Node::new();
let mut right = box Node::new();
init_tree(&mut *left, n - 1);
init_tree(&mut *right, n - 1);
root.left = Some(left);
root.right = Some(right);
}
}
That is a lot simpler to look at, &mut *left being read right to left as “dereference left (which will get you a Node from a Box<Node>) and then take a mutable reference to it (which will get you a &mut Node).

Related

Recursive closure inside a function [duplicate]

This is a very simple example, but how would I do something similar to:
let fact = |x: u32| {
match x {
0 => 1,
_ => x * fact(x - 1),
}
};
I know that this specific example can be easily done with iteration, but I'm wondering if it's possible to make a recursive function in Rust for more complicated things (such as traversing trees) or if I'm required to use my own stack instead.
There are a few ways to do this.
You can put closures into a struct and pass this struct to the closure. You can even define structs inline in a function:
fn main() {
struct Fact<'s> { f: &'s dyn Fn(&Fact, u32) -> u32 }
let fact = Fact {
f: &|fact, x| if x == 0 {1} else {x * (fact.f)(fact, x - 1)}
};
println!("{}", (fact.f)(&fact, 5));
}
This gets around the problem of having an infinite type (a function that takes itself as an argument) and the problem that fact isn't yet defined inside the closure itself when one writes let fact = |x| {...} and so one can't refer to it there.
Another option is to just write a recursive function as a fn item, which can also be defined inline in a function:
fn main() {
fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }
println!("{}", fact(5));
}
This works fine if you don't need to capture anything from the environment.
One more option is to use the fn item solution but explicitly pass the args/environment you want.
fn main() {
struct FactEnv { base_case: u32 }
fn fact(env: &FactEnv, x: u32) -> u32 {
if x == 0 {env.base_case} else {x * fact(env, x - 1)}
}
let env = FactEnv { base_case: 1 };
println!("{}", fact(&env, 5));
}
All of these work with Rust 1.17 and have probably worked since version 0.6. The fn's defined inside fns are no different to those defined at the top level, except they are only accessible within the fn they are defined inside.
As of Rust 1.62 (July 2022), there's still no direct way to recurse in a closure. As the other answers have pointed out, you need at least a bit of indirection, like passing the closure to itself as an argument, or moving it into a cell after creating it. These things can work, but in my opinion they're kind of gross, and they're definitely hard for Rust beginners to follow. If you want to use recursion but you have to have a closure, for example because you need something that implements FnOnce() to use with thread::spawn, then I think the cleanest approach is to use a regular fn function for the recursive part and to wrap it in a non-recursive closure that captures the environment. Here's an example:
let x = 5;
let fact = || {
fn helper(arg: u64) -> u64 {
match arg {
0 => 1,
_ => arg * helper(arg - 1),
}
}
helper(x)
};
assert_eq!(120, fact());
Here's a really ugly and verbose solution I came up with:
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
fn main() {
let weak_holder: Rc<RefCell<Weak<dyn Fn(u32) -> u32>>> =
Rc::new(RefCell::new(Weak::<fn(u32) -> u32>::new()));
let weak_holder2 = weak_holder.clone();
let fact: Rc<dyn Fn(u32) -> u32> = Rc::new(move |x| {
let fact = weak_holder2.borrow().upgrade().unwrap();
if x == 0 {
1
} else {
x * fact(x - 1)
}
});
weak_holder.replace(Rc::downgrade(&fact));
println!("{}", fact(5)); // prints "120"
println!("{}", fact(6)); // prints "720"
}
The advantages of this are that you call the function with the expected signature (no extra arguments needed), it's a closure that can capture variables (by move), it doesn't require defining any new structs, and the closure can be returned from the function or otherwise stored in a place that outlives the scope where it was created (as an Rc<Fn...>) and it still works.
Closure is just a struct with additional contexts. Therefore, you can do this to achieve recursion (suppose you want to do factorial with recursive mutable sum):
#[derive(Default)]
struct Fact {
ans: i32,
}
impl Fact {
fn call(&mut self, n: i32) -> i32 {
if n == 0 {
self.ans = 1;
return 1;
}
self.call(n - 1);
self.ans *= n;
self.ans
}
}
To use this struct, just:
let mut fact = Fact::default();
let ans = fact.call(5);

Rust Cacher with HashMap Chapter 13

As suggested in Chapter 13, I am trying to implement the Cacher with a HashMap. Unlike some of the other questions asked, I am trying to follow the aproach taken by the author and use Option as value in the Cacher.
struct Cacher<T>
where T: Fn(u32) -> u32, //struct needs to know Type of closure(aka calc)
{
calc: T,
value: Option<HashMap<u32, u32>>
}
impl<T> Cacher<T>
where T: Fn(u32) -> u32,{
fn new(calculation: T) -> Cacher<T>{
Cacher {
calc: calculation,
value: None
}
}
fn value(&mut self, arg: u32) -> u32 {
match &mut self.value {
Some(map) => {
let v = map.entry(arg).or_insert((self.calc)(arg));
*v
},
None => {
let mut map = HashMap::new();
let v = map.insert(arg, (self.calc)(arg)).unwrap();
self.value = Some(map);
v
}
}
}
}
The code compiles but even running a simple:
let mut expensive_res = Cacher::new( |num| {
println!("calculating slowly....{}", num);
thread::sleep(Duration::from_secs(1));
num + 100
});
println!("{}", expensive_res.value(1));
I get an Panic when running it.
thread 'main' panicked at 'called Option::unwrap() on a None value'.
Any suggestions? Why is unwrap here a None?
Many thanks
let mut map = HashMap::new();
let v = map.insert(arg, (self.calc)(arg)).unwrap();
self.value = Some(map);
v
I think you're confused about what HashMap::insert returns: it returns the previous value for the key, if any (which is why it's an Option).
So when you've just created an empty map and you insert into it for the first time... it returns None because there can not have been an existing value there. Therefore this codepath can only panic.
incidentally the code is overcomplicated due to the completely unnecessary Option<HashMap>:
The hash map is initially created with a capacity of 0, so it will not allocate until it is first inserted into.
So putting aside the idea that this would serve any role as a temporal optimisation, it doesn't even do so, because allocation is delayed until first insertion.
There is an other issue, on both codepaths: Rust is an eager language, which means:
let v = map.entry(arg).or_insert((self.calc)(arg));
is equivalent to:
let mut entry = map.entry(arg);
let default = (self.calc)(arg);
let v = entry.or_insert(default);
so you're running the computation even when it's already in the cache, aka instead of trading memory for CPU this implementation just wastes memory.

how to correctly return a reference to a mutated linked list in rust?

I am solving a leetcode problem in Rust, it's a linked list problem.
The part that I am stuck at is that I have a working algorithm, but I wasn't able to return from the function, below is my solution
pub fn remove_nth_from_end(head: Option<Box<ListNode>>, n: i32) -> Option<Box<ListNode>> {
let mut cursor = head.clone().unwrap();
let mut count: i32 = 0;
while cursor.next != None {
count += 1;
cursor = cursor.next.unwrap();
}
let mut n = count - n;
let mut new_cursor = head.unwrap();
while n != 0 {
n -= 1;
new_cursor = new_cursor.next.unwrap();
}
new_cursor.next = new_cursor.next.unwrap().next;
head // <- error: used of moved value
}
I first clone the head so that I can iterate through the linked list to get its total number of nodes.
Then, I will have to remove one node from the list, hence I'm not cloning the head, instead I use it directly, in this case the variable is moved. So after I am done removing the node, I would like to return the head, so that I can return the whole linked list.
However, because of the ownership system in rust, I wasn't able to return a moved value. The problem is I couldn't clone the value as well because if I were to clone, then the head is no longer pointing to the linked list where I removed one node from it.
How would one solve this kind of issue in Rust? I am fairly new to Rust, just picked up the language recently.
One way is to use &mut over the nodes and then use Option::take to take ownership of the nodes while leaving None behind. Use those combinations to mutate the list:
impl Solution {
pub fn remove_nth_from_end(mut head: Option<Box<ListNode>>, mut n: i32) -> Option<Box<ListNode>> {
match n {
0 => head.and_then(|node| node.next),
_ => {
let mut new_head = &mut head;
while n > 0 {
new_head = if let Some(next) = new_head {
&mut next.next
} else {
return head;
};
n -= 1;
}
let to_skip = new_head.as_mut().unwrap().next.take();
new_head.as_mut().map(|node| {
node.next = if let Some(mut other_node) = to_skip {
other_node.next.take()
} else {
None
};
});
head
}
}
}
}
Playground
Disclaimer: This do not implement it working from the end of the list but from the beginning of it. Didn't realize that part, but that should be the problem itself.

Can't do breadth-first search on a binary tree in Rust

I've implemented a binary tree in Rust as a learning project but failed to transverse it to print the tree in a breadth-first search fashion.
The issue is that I can't reassign the search queue (children) because it's borrowed and doesn't live long enough.
https://gist.github.com/varshard/3874803cd035e27facb67c59e89c3c1c#file-binary_tree-rs-L39
How can I correct this?
use std::fmt::Display;
type Branch<'a, T> = Option<Box<Node<'a, T>>>;
struct Node<'a, T: PartialOrd + Display> {
value: &'a T,
left: Branch<'a, T>,
right: Branch<'a, T>
}
impl<'a, T: PartialOrd + Display> Node<'a, T> {
fn insert(&mut self, value: &'a T) {
let target_node = if value > self.value { &mut self.right } else { &mut self.left };
match target_node {
Some(ref mut node) => node.insert(value),
None => {
let new_node = Node{ value: value, left: None, right: None};
*target_node = Some(Box::new(new_node))
}
}
}
fn display(&'a self) {
let mut children: Vec<Option<&Node<'a, T>>> = Vec::new();
children.push(Some(self));
while children.len() > 0 {
for child in &children {
match child {
Some(node) => {
print!("{} ", node.value);
},
None => {
print!(" ")
}
}
}
println!("");
// Error: children doesn't live long enough;
children = self.to_vec(&children);
}
}
fn to_vec(&self, nodes: &'a Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
let mut children: Vec<Option<&Node<'a, T>>> = Vec::new();
for node_option in nodes {
match node_option {
Some(node) => {
match &node.left {
Some(left) => {
children.push(Some(left));
match &node.right {
Some(right) => {
children.push(Some(right));
},
None => {
children.push(None);
}
}
},
None => {
children.push(None);
match &node.right {
Some(right) => {
children.push(Some(right));
},
None => {
children.push(None);
}
}
}
}
},
None => {}
}
}
children
}
}
fn main() {
let root_val = 5;
let mut root = Node{ value: &root_val, left: None, right: None };
root.insert(&3);
root.insert(&4);
root.insert(&1);
root.insert(&6);
root.display();
}
Copying my answer from this reddit comment:
There's a way to directly fix your problem, but I think there are better options for making the code easier to write and understand. For the direct fix, you can make some lifetime adjustments. Instead of
fn to_vec(&self, nodes: &'a Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
You need:
fn to_vec<'b>(&self, nodes: &Vec<Option<&'b Node<'a, T>>>) -> Vec<Option<&'b Node<'a, T>>>
What's the difference there? In the first case we're saying that nodes is a &'a Vec. That is, a borrow of a Vec that lives as long as the value references inside your tree. That's a long time to live, and it's what the compiler's getting angry about.
Now, if you just take the 'a off of that &Vec, the compiler complains about something else:
|
42 | fn to_vec(&self, nodes: &Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
| ------------ -------------------------
| |
| this parameter and the return type are declared with different lifetimes...
...
76 | children
| ^^^^^^^^ ...but data from `nodes` is returned here
Maybe this is the error that pushed you to put the 'a on the &Vec in the first place. We need to solve it a different way. The important thing to understand here is that the return value doesn't contain references directly into the nodes vector, but it does contain copies of the nodes vector's contents, the &Node references. We need to tell the compiler that even though the nodes reference doesn't live very long, its contents do live longer. That's why we create the new lifetime 'b in my fix above.
This is objectively very confusing. Personally, I prefer to avoid solving these tricky problems, by just keeping things alive longer instead of reasoning about exactly how long they live. The source of the difficulty is that we're destroying the children vector on line 39. If we were able to keep it around, and just keep emptying it and refilling it, Rust would give us a much easier time. Have you considered using a std::collections::VecDeque instead of a Vec here? You could construct it once outside of your while-loop, and then you could pass &mut children around, without worrying very much about its lifetime. I think a queue is usually the go-to data structure for a breadth-first traversal, with new children added to the back, and the traversal itself reading from the front.

Adding an append method to a singly linked list

I was looking through the singly linked list example on rustbyexample.com and I noticed the implementation had no append method, so I decided to try and implement it:
fn append(self, elem: u32) -> List {
let mut node = &self;
loop {
match *node {
Cons(_, ref tail) => {
node = tail;
},
Nil => {
node.prepend(elem);
break;
},
}
}
return self;
}
The above is one of many different attempts, but I cannot seem to find a way to iterate down to the tail and modify it, then somehow return the head, without upsetting the borrow checker in some way.
I am trying to figure out a solution that doesn't involve copying data or doing additional bookkeeping outside the append method.
As described in Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time, you need to transfer ownership of the mutable reference when performing iteration. This is needed to ensure you never have two mutable references to the same thing.
We use similar code as that Q&A to get a mutable reference to the last item (back) which will always be the Nil variant. We then call it and set that Nil item to a Cons. We wrap all that with a by-value function because that's what the API wants.
No extra allocation, no risk of running out of stack frames.
use List::*;
#[derive(Debug)]
enum List {
Cons(u32, Box<List>),
Nil,
}
impl List {
fn back(&mut self) -> &mut List {
let mut node = self;
loop {
match {node} {
&mut Cons(_, ref mut next) => node = next,
other => return other,
}
}
}
fn append_ref(&mut self, elem: u32) {
*self.back() = Cons(elem, Box::new(Nil));
}
fn append(mut self, elem: u32) -> Self {
self.append_ref(elem);
self
}
}
fn main() {
let n = Nil;
let n = n.append(1);
println!("{:?}", n);
let n = n.append(2);
println!("{:?}", n);
let n = n.append(3);
println!("{:?}", n);
}
When non-lexical lifetimes are enabled, this function can be more obvious:
fn back(&mut self) -> &mut List {
let mut node = self;
while let Cons(_, next) = node {
node = next;
}
node
}
As the len method is implemented recursively, I have done the same for the append implementation:
fn append(self, elem: u32) -> List {
match self {
Cons(current_elem, tail_box) => {
let tail = *tail_box;
let new_tail = tail.append(elem);
new_tail.prepend(current_elem)
}
Nil => {
List::new().prepend(elem)
}
}
}
One possible iterative solution would be to implement append in terms of prepend and a reverse function, like so (it won't be as performant but should still only be O(N)):
// Reverses the list
fn rev(self) -> List {
let mut result = List::new();
let mut current = self;
while let Cons(elem, tail) = current {
result = result.prepend(elem);
current = *tail;
}
result
}
fn append(self, elem: u32) -> List {
self.rev().prepend(elem).rev()
}
So, it's actually going to be slightly more difficult than you may think; mostly because Box is really missing a destructive take method which would return its content.
Easy way: the recursive way, no return.
fn append_rec(&mut self, elem: u32) {
match *self {
Cons(_, ref mut tail) => tail.append_rec(elem),
Nil => *self = Cons(elem, Box::new(Nil)),
}
}
This is relatively easy, as mentioned.
Harder way: the recursive way, with return.
fn append_rec(self, elem: u32) -> List {
match self {
Cons(e, tail) => Cons(e, Box::new((*tail).append_rec(elem))),
Nil => Cons(elem, Box::new(Nil)),
}
}
Note that this is grossly inefficient. For a list of size N, we are destroying N boxes and allocating N new ones. In place mutation (the first approach), was much better in this regard.
Harder way: the iterative way, with no return.
fn append_iter_mut(&mut self, elem: u32) {
let mut current = self;
loop {
match {current} {
&mut Cons(_, ref mut tail) => current = tail,
c # &mut Nil => {
*c = Cons(elem, Box::new(Nil));
return;
},
}
}
}
Okay... so iterating (mutably) over a nested data structure is not THAT easy because ownership and borrow-checking will ensure that:
a mutable reference is never copied, only moved,
a mutable reference with an outstanding borrow cannot be modified.
This is why here:
we use {current} to move current into the match,
we use c # &mut Nil because we need a to name the match of &mut Nil since current has been moved.
Note that thankfully rustc is smart enough to check the execution path and detect that it's okay to continue looping as long as we take the Cons branch since we reinitialize current in that branch, however it's not okay to continue after taking the Nil branch, which forces us to terminate the loop :)
Harder way: the iterative way, with return
fn append_iter(self, elem: u32) -> List {
let mut stack = List::default();
{
let mut current = self;
while let Cons(elem, tail) = current {
stack = stack.prepend(elem);
current = take(tail);
}
}
let mut result = List::new();
result = result.prepend(elem);
while let Cons(elem, tail) = stack {
result = result.prepend(elem);
stack = take(tail);
}
result
}
In the recursive way, we were using the stack to keep the items for us, here we use a stack structure instead.
It's even more inefficient than the recursive way with return was; each node cause two deallocations and two allocations.
TL;DR: in-place modifications are generally more efficient, don't be afraid of using them when necessary.

Resources