Rust cannot move out of dereference pointer - pointers

I try to run this code:
impl FibHeap {
fn insert(&mut self, key: int) -> () {
let new_node = Some(box create_node(key, None, None));
match self.min{
Some(ref mut t) => t.right = new_node,
None => (),
};
println!("{}",get_right(self.min));
}
}
fn get_right(e: Option<Box<Node>>) -> Option<Box<Node>> {
match e {
Some(t) => t.right,
None => None,
}
}
And get error
error: cannot move out of dereference of `&mut`-pointer
println!("{}",get_right(self.min));
^
I dont understand why I get this problem, and what I must use to avoid problem.

Your problem is that get_right() accepts Option<Box<Node>>, while it should really accept Option<&Node> and return Option<&Node> as well. The call site should be also changed appropriately.
Here is the explanation. Box<T> is a heap-allocated box. It obeys value semantics (that is, it behaves like plain T except that it has associated destructor so it is always moved, never copied). Hence passing just Box<T> into a function means giving up ownership of the value and moving it into the function. However, it is not what you really want and neither can do here. get_right() function only queries the existing structure, so it does not need ownership. And if ownership is not needed, then references are the answer. Moreover, it is just impossible to move the self.min into a function, because self.min is accessed through self, which is a borrowed pointer. However, you can't move out from a borrowed data, it is one of the basic safety guarantees provided by the compiler.
Change your get_right() definition to something like this:
fn get_right(e: Option<&Node>) -> Option<&Node> {
e.and_then(|n| n.right.as_ref().map(|r| &**r))
}
Then println!() call should be changed to this:
println!("{}", get_right(self.min.map(|r| &**r))
Here is what happens here. In order to obtain Option<&Node> from Option<Box<Node>> you need to apply the "conversion" to insides of the original Option. There is a method exactly for that, called map(). However, map() takes its target by value, which would mean moving Box<Node> into the closure. However, we only want to borrow Node, so first we need to go from Option<Box<Node>> to Option<&Box<Node>> in order for map() to work.
Option<T> has a method, as_ref(), which takes its target by reference and returns Option<&T>, a possible reference to the internals of the option. In our case it would be Option<&Box<Node>>. Now this value can be safely map()ped over since it contains a reference and a reference can be freely moved without affecting the original value.
So, next, map(|r| &**r) is a conversion from Option<&Box<Node>> to Option<&Node>. The closure argument is applied to the internals of the option if they are present, otherwise None is just passed through. &**r should be read inside out: &(*(*r)), that is, first we dereference &Box<Node>, obtaining Box<Node>, then we dereference the latter, obtaining just Node, and then we take a reference to it, finally getting &Node. Because these reference/dereference operations are juxtaposed, there is no movement/copying involved. So, we got an optional reference to a Node, Option<&Node>.
You can see that similar thing happens in get_right() function. However, there is also a new method, and_then() is called. It is equivalent to what you have written in get_right() initially: if its target is None, it returns None, otherwise it returns the result of Option-returning closure passed as its argument:
fn and_then<U>(self, f: |T| -> Option<U>) -> Option<U> {
match self {
Some(e) => f(e),
None => None
}
}
I strongly suggest reading the official guide which explains what ownership and borrowing are and how to use them, because these are the very foundation of Rust language and it is very important to grasp them in order to be productive with Rust.

Related

How to avoid cloning parts when changing a mutable struct while recursion over that struct

I try to go recursively through a rose tree. The following code also works as intended but I still have the problem that I need to clone the value due to issues with the borrow checker. Therefore, it would be nice if there is a way to change from cloning to something better.
Without the clone() rust complains (rightfully) that I borrow self mutable by looking at the child nodes and the second time in the closure.
The whole structure and code is more complicated and bigger than shown below but that are the core elements. Do I have to change the data structure or do I miss something obvious? If the data structure is the issue how would you change it?
Also, the NType enum seems kinda useless here but I have some additional kinds that I have to consider. Here Inner nodes always have children and Outer nodes never.
enum NType{
Inner,
Outer
}
#[derive(Eq, PartialEq, Clone, Debug)]
struct Node {
// isn't a i32 actually. In my real program it's another struct
count: i32,
n_type: NType,
children: Option<Vec<usize>>
}
#[derive(Eq, PartialEq, Clone, Debug)]
struct Tree {
nodes: Vec<Node>,
}
impl Tree{
pub fn calc(&mut self, features: &Vec<i32>) -> i32{
// root is the last node
self.calc_h(self.nodes.len() - 1, features);
self.nodes[self.nodes.len() - 1].count.clone()
}
fn calc_h(&mut self, current: usize, features: &Vec<i32>){
// do some other things to decide where to go into recursion and where not to
// also use the features
if self.nodes[current].n_type == Inner{
//cloneing is very expensiv and destroys the performance
self.nodes[current].children.as_ref().unwrap().clone().iter().for_each(|&n| self.calc_h(n, features));
self.do_smt(current)
}
self.do_smt(current)
}
}
Edit:
Lagerbaer suggested to use as_mut but that results into current being a &mut usize and that doesn't really solve the problem.
changed childs into children
The correct plural of child is children so this is what I will refer to in this answer. Presumably this is what childs means in your code.
Since node.children is already an Option, the best solution would be to .take() the vector out of the node at the start of the iteration and put it in at the end. This way we avoid holding a reference to tree.nodes during the iteration.
if self.nodes[current].n_type == Inner {
let children = self.nodes[current].children.take().unwrap();
for &child in children.iter() {
self.calc_h(child, features);
}
self.nodes[current].children = Some(children);
}
Note that the behavior is different from your original code in case of cycles, but this is not something you need to worry about if the rest of the tree is implemented correctly.

How to check if a Box is a null pointer?

I want to implement a stack using pointers or something. How can I check if a Box is a null pointer? I seen some code with Option<Box<T>> and Box<Option<T>> but I don't understand this. This is as far as I went:
struct Node {
value: i32,
next: Box<Node>,
}
struct Stack {
top: Box<Node>,
}
Box<T> can never be NULL, therefore there is nothing to check.
Box<T> values will always be fully aligned, non-null pointers
— std::box
You most likely wish to use Option to denote the absence / presence of a value:
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
See also:
Should we use Option or ptr::null to represent a null pointer in Rust?
How to set a field in a struct with an empty value?
What is the null pointer optimization in Rust?
You don't want null. null is an unsafe antipattern even in languages where you have to use it, and thankfully Rust rids us of the atrocity. Box<T> always contains a T, never null. Rust has no concept of null.
As you've correctly pointed out, if you want a value to be optional, you use Option<T>. Whether you do Box<Option<T>> or Option<Box<T>> really doesn't matter that much, and someone who knows a bit more about the lower-level side of things can chime in on which is more efficient.
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
The Option says "this may or may not exist" and the Box says "this value is on the heap. Now, the nice thing about Option that makes it infinitely better than null is that you have to check it. You can't forget or the compiler will complain. The typical way to do so is with match
match my_stack.top {
None => {
// Top of stack is not present
}
Some(x) => {
// Top of stack exists, and its value is x of type Box<T>
}
}
There are tons of helper methods on the Option type itself to deal with common patterns. Below are just a few of the most common ones I use. Note that all of these can be implemented in terms of match and are just convenience functions.
The equivalent of the following Java code
if (value == null) {
result = null;
} else {
result = ...;
}
is
let result = value.map(|v| ...)
Or, if the inner computation can feasibly produce None as well,
let result = value.and_then(|v| ...)
If you want to provide a default value, say zero, like
if (value == null) {
result = 0;
} else {
result = value;
}
Then you want
result = value.unwrap_or(0)
It's probably best to stop thinking in terms of how you would handle null and start learning Option<T> from scratch. Once you get the hang of it, it'll feel ten times safer and more ergonomic than null checks.
A Box<T> is a pointer to some location on the heap that contains some data of type T. Rust guarantees that Box<T> will never be a null pointer, i.e the address should always be valid as long as you aren't doing anything weird and unsafe.
If you need to represent a value that might not be there (e.g this node is the last node, so there is no next node), you can use the Option type like so
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
Now, with Option<Box<Node>>, Node can either have a next Node or no next node. We can check if the Option is not None like so
fn print_next_node_value(node: &Node) {
match &node.next {
Some(next) => println!("the next value is {}", next.value),
None => println!("there is no next node")
}
}
Because a Box is just a pointer to some location on the heap, it can be better to use Option<Box<T>> instead of Box<Option<T>>. This is because the second one will allocate an Option<T> on the heap, while the first one will not. Additionally, Option<Box<T>> and Box<T> are equally big (both are 8 bytes). This is because Rust knows that Box<T> can never be all zeros (i.e can never be the null pointer), so it can use the all-0's state to represent the None case of Option<Box<T>>.

Is there a more friendly RefCell-like object?

I'm looking for a class much like Vec<RefCell<T>>, in that it is the ultimate owner & allocator of all of its data, yet different pieces of the array can be be mutably borrowed by multiple parties indefinitely.
I emphasize indefinitely because of course pieces of Vec<T> can also be mutably borrowed by multiple parties, but doing so involves making a split which can only be resolved after the parties are done borrowing.
Vec<RefCell<T>> seems to be a world of danger and many ugly if statements checking borrow_state, which seems to be unstable. If you do something wrong, then kablammo! Panic! This is not what a lending library is like. In a lending library, if you ask for a book that isn't there, they tell you "Oh, it's checked out." Nobody dies in an explosion.
So I would like to write code something like this:
let mut a = LendingLibrary::new();
a.push(Foo{x:10});
a.push(Foo{x:11});
let b1 = a.get(0); // <-- b1 is an Option<RefMut<Foo>>
let b2 = a.get(1); // <-- b2 is an Option<RefMut<Foo>>
// the 0th element has already been borrowed, so...
let b3 = a.get(0); // <-- b3 is Option::None
Does such a thing exist? Or is there another canonical way to get this kind of behavior? A kind of "friendly RefCell"?
If the answer happens to be yes, is there also a threadsafe variant?
RefCell is not designed for long-lived borrows. The typical use case is that in a function, you'll borrow the RefCell (either mutably or immutably), work with the value, then release the borrow before returning. I'm curious to know how you're hoping to recover from a borrowed RefCell in a single-threaded context.
The thread-safe equivalent to RefCell is RwLock. It has try_read and try_write functions that do not block or panic if an incompatible lock is still acquired (on any thread, including the current thread). Contrarily to RefCell, it makes sense to just retry later if locking a RwLock fails, since another thread might just happen to have locked it at the same time.
If you end up always using write or try_write, and never read or try_read, then you should probably use the simpler Mutex instead.
#![feature(borrow_state)]
use std::cell::{RefCell, RefMut, BorrowState};
struct LendingLibrary<T> {
items: Vec<RefCell<T>>
}
impl<T> LendingLibrary<T> {
fn new(items: Vec<T>) -> LendingLibrary<T> {
LendingLibrary {
items: items.into_iter().map(|e| RefCell::new(e)).collect()
}
}
fn get(&self, item: usize) -> Option<RefMut<T>> {
self.items.get(item)
.and_then(|cell| match cell.borrow_state() {
BorrowState::Unused => Some(cell.borrow_mut()),
_ => None
})
}
}
fn main() {
let lib = LendingLibrary::new(vec![1, 2, 3]);
let a = lib.get(0); // Some
let b = lib.get(1); // Some
let a2 = lib.get(0); // None
}
This currently requires a nightly release to work.

Weird behaviour with struct constructors

I've written a basic Node struct in D, designed to be used as a part of a tree-like structure. The code is as follows:
import std.algorithm: min;
alias Number = size_t;
struct Node {
private {
Node* left, right, parent;
Number val;
}
this(Number n) {val = n;}
this(ref Node u, ref Node v) {
this.left = &u;
this.right = &v;
val = min(u.val, v.val);
u.parent = &this;
v.parent = &this;
}
}
Now, I wrote a simple function which is supposed to give me a Node (meaning a whole tree) with the argument array providing the leaves, as follows.
alias Number = size_t;
Node make_tree (Number[] nums) {
if (nums.length == 1) {
return Node(nums[0]);
} else {
Number half = nums.length/2;
return Node(make_tree(nums[0..half]), make_tree(nums[half..$]));
}
}
Now, when I try to run it through dmd, I get the following error message:
Error: constructor Node.this (ulong n) is not callable using argument types (Node, Node)
This makes no sense to me - why is it trying to call a one-argument constructor when given two arguments?
The problem has nothing to do with constructors. It has to do with passing by ref. The constructor that you're trying to use
this(ref Node u, ref Node v) {...}
accepts its arguments by ref. That means that they must be lvalues (i.e. something that can be on the left-hand side of an assignment). But you're passing it the result of a function call which does not return by ref (so, it's returning a temporary, which is an rvalue - something that can go on the right-hand side of an assignment but not the left). So, what you're trying to do is illegal. Now, the error message isn't great, since it's giving an error with regards to the first constructor rather than the second, but regardless, you don't have a constructor which matches what you're trying to do. At the moment, I can think of 3 options:
Get rid of the ref on the constructor's parameters. If you're only going to be passing it the result of a function call like you're doing now, having it accept ref doesn't help you anyway. The returned value will be moved into the function's parameter, so no copy will take place, and ref isn't buying you anything. Certainly, assigning the return values to local variables so that you can pass them to the constructor as it's currently written would lose you something, since then you'd be making unnecessary copies.
Overload the constructor so that it accepts either ref or non-ref. e.g.
void foo(ref Bar b) { ... }
void foo(Bar b) { foo(b); } //this calls the other foo
In general, this works reasonably well when you have one parameter, but it would be a bit annoying here, because you end up with an exponential explosion of function signatures as you add parameters. So, for your constructor, you'd end up with
this(ref Node u, ref Node v) {...}
this(ref Node u, Node v) { this(u, v); }
this(Node u, ref Node v) { this(u, v); }
this(Node u, Node v) { this(u, v); }
And if you added a 3rd parameter, you'd end up with eight overloads. So, it really doesn't scale beyond a single parameter.
Templatize the constructor and use auto ref. This essentially does what #2 does, but you only have to write the function once:
this()(auto ref Node u, auto ref Node v) {...}
This will then generate a copy of the function to match the arguments given (up to 4 different versions of it with the full function body in each rather than 3 of them just forwarding to the 4th one), but you only had to write it once. And in this particular case, it's probably reasonable to templatize the function, since you're dealing with a struct. If Node were a class though, it might not make sense, since templated functions can't be virtual.
So, if you really want to be able to pass by ref, then in this particular case, you should probably go with #3 and templatize the constructor and use auto ref. However, personally, I wouldn't bother. I'd just go with #1. Your usage pattern here wouldn't get anything from auto ref, since you're always passing it two rvalues, and your Node struct isn't exactly huge anyway, so while you obviously wouldn't want to copy it if you don't need to, copying an lvalue to pass it to the constructor probably wouldn't matter much unless you were doing it a lot. But again, you're only going to end up with a copy if you pass it an lvalue, since an rvalue can be moved rather than copied, and you're only passing it rvalues right now (at least with the code shown here). So, unless you're doing something different with that constructor which would involve passing it lvalues, there's no point in worrying about lvalues - or about the Nodes being copied when they're returned from a function and passed into the constructor (since that's a move, not a copy). As such, just removing the refs would be the best choice.

Why can't I reuse a funtion's borrowed pointer

I don't understand why rustc gives me this error error: use of moved value: 'f' at compile time, with the following code:
fn inner(f: &fn(&mut int)) {
let mut a = ~1;
f(a);
}
fn borrow(b: &mut int, f: &fn(&mut int)) {
f(b);
f(b); // can reuse borrowed variable
inner(f); // shouldn't f be borrowed?
// Why can't I reuse the borrowed reference to a function?
// ** error: use of moved value: `f` **
//f(b);
}
fn main() {
let mut a = ~1;
print!("{}", (*a));
borrow(a, |x: &mut int| *x+=1);
print!("{}", (*a));
}
I want to reuse the closure after I pass it as argument to another function. I am not sure if it is a copyable or a stack closure, is there a way to tell?
That snippet was for rustc 0.8. I managed to compile a different version of the code with the latest rustc (master: g67aca9c), changing the &fn(&mut int) to a plain fn(&mut int) and using normal functions instead of a closure, but how can I get this to work with a closure?
The fact of the matter is that &fn is not actually a borrowed pointer in the normal sense. It's a closure type. In master, the function types have been fixed up a lot and the syntax for such things has changed to |&mut int|—if you wanted a borrowed pointer to a function, for the present you need to type it &(fn (...)) (&fn is marked obsolete syntax for now, to help people migrating away from it, because it's a completely distinct type).
But for closures, you can then go passing them around by reference: &|&mut int|.

Resources