Avoid partially moved value when taking ownership of a recursive data structure? - recursion

Say I have a recursive data structure like a singly-linked list, and I want to write a recursive function to insert a value after the last node*:
struct Node {
next: Option<Box<Node>>,
val: i32,
}
fn put_after_node(maybe_node: Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
None => Box::new(Node { next: None, val: val }),
Some(mut node) => {
// compile error on next line: use of partially moved value: `node`
node.next = Some(put_after_node(node.next, val));
node
}
}
}
Q: How do I avoid the compile error complaining that node has been partially moved?
Failed fix #1: Avoiding taking ownership of the function's arguments, by taking maybe_node: &mut Option<Box<Node>> instead. Failed because I need to add a new node and pass that back up the stack, and if I only have a mutable reference then I need to dereference it, which causes an illegal move out of borrowed value:
fn put_after_node(maybe_node: &mut Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
&mut None => Box::new(Node { next: None, val: val }),
&mut Some(ref mut node) => {
node.next = Some(put_after_node(&mut node.next, val));
*node // compile error: cannot move out of borrowed content
}
}
}
Failed fix #2: Return a reference to a new node instead (fn ... -> &Box<Node>). Failed because the new node doesn't live long enough (or at least, I can't work out how to specify the lifetime for the new node such that it does live at least as long as the reference to it that'd be returned from the function).
fn put_after_node(maybe_node: &mut Option<Box<Node>>, val: i32) -> &Box<Node> {
match maybe_node {
// compile error on next line: borrowed value does not live long enough
&mut None => &Box::new(Node { next: None, val: val }),
&mut Some(ref mut node) => {
// compile error on next line: cannot move out of borrowed content
node.next = Some(*put_after_node(&mut node.next, val));
node
}
}
}
(* The original snippet is a simplified version of a Rust transliteration that I'm attempting to do of this red black tree implementation's put(). I realise that the minimal example I've outlined here would be better as a loop, but that isn't the case for the code I'm actually trying to write.)
Update: I don't think this is a dup of `cannot move out of dereference of `&mut`-pointer` while building a sorted linked list because a) I'm trying to deal with a different error message & b) my fn takes self - not &mut self. Having said that, I will probably try to rewrite it to take &mut self, so thanks for the pointer #shepmaster.

Take the Option's value using take() (which itself uses mem::replace() under the covers):
fn put_after_node(maybe_node: Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
None => Box::new(Node { next: None, val: val }),
Some(mut node) => {
// note the node.next.take()
node.next = Some(put_after_node(node.next.take(), val));
node
}
}
}

Related

What is the most efficient way to return/move a Vec/Field in rust while also emptying it? [duplicate]

I have a struct with a field:
struct A {
field: SomeType,
}
Given a &mut A, how can I move the value of field and swap in a new value?
fn foo(a: &mut A) {
let mut my_local_var = a.field;
a.field = SomeType::new();
// ...
// do things with my_local_var
// some operations may modify the NEW field's value as well.
}
The end goal would be the equivalent of a get_and_set() operation. I'm not worried about concurrency in this case.
Use std::mem::swap().
fn foo(a: &mut A) {
let mut my_local_var = SomeType::new();
mem::swap(&mut a.field, &mut my_local_var);
}
Or std::mem::replace().
fn foo(a: &mut A) {
let mut my_local_var = mem::replace(&mut a.field, SomeType::new());
}
If your type implements Default, you can use std::mem::take:
#[derive(Default)]
struct SomeType;
fn foo(a: &mut A) {
let mut my_local_var = std::mem::take(&mut a.field);
}
If your field happens to be an Option, there's a specific method you can use — Option::take:
struct A {
field: Option<SomeType>,
}
fn foo(a: &mut A) {
let old = a.field.take();
// a.field is now None, old is whatever a.field used to be
}
The implementation of Option::take uses mem::take, just like the more generic answer above shows, but it is wrapped up nicely for you:
pub fn take(&mut self) -> Option<T> {
mem::take(self)
}
See also:
Temporarily move out of borrowed content
Change enum variant while moving the field to the new variant

Why does a node in a linked list using raw pointers become corrupted?

I am struggling to learn raw pointers while implementing a linked list. A simple piece of code gives me unintended results for which I struggle to find any explanation whatsoever:
use std::cmp::PartialEq;
use std::default::Default;
use std::ptr;
pub struct LinkedListElement<T> {
pub data: T,
pub next: *mut LinkedListElement<T>,
}
pub struct LinkedList<T> {
head: *mut LinkedListElement<T>,
}
impl<T: PartialEq> LinkedListElement<T> {
pub fn new(elem: T, next: Option<*mut LinkedListElement<T>>) -> LinkedListElement<T> {
let mut_ptr = match next {
Some(t) => t,
None => ptr::null_mut(),
};
let new_elem = LinkedListElement {
data: elem,
next: mut_ptr,
};
if !mut_ptr.is_null() {
println!(
"post create ll mut ptr: {:p}, post create ll mut ptr next {:p}",
mut_ptr,
unsafe { (*mut_ptr).next }
);
}
new_elem
}
}
impl<T: PartialEq + Default> LinkedList<T> {
pub fn new(elem: T) -> LinkedList<T> {
LinkedList {
head: &mut LinkedListElement::new(elem, None),
}
}
pub fn insert(&mut self, elem: T) {
println!("head: {:p} . next: {:p}", self.head, unsafe {
(*self.head).next
});
let next = Some(self.head);
let mut ll_elem = LinkedListElement::new(elem, next);
println!(
"before pointer head: {:p}. before pointer next {:p}",
self.head,
unsafe { (*self.head).next }
);
let ll_elem_ptr = &mut ll_elem as *mut LinkedListElement<T>;
self.head = ll_elem_ptr;
}
}
fn main() {
let elem: i32 = 32;
let second_elem: i32 = 64;
let third_elem: i32 = 72;
let mut list = LinkedList::new(elem);
list.insert(second_elem);
list.insert(third_elem);
}
(playground)
This code gives me the following output:
head: 0x7ffe163275e8 . next: 0x0
post create ll mut ptr: 0x7ffe163275e8, post create ll mut ptr next 0x0
before pointer head: 0x7ffe163275e8. before pointer next 0x0
head: 0x7ffe16327560 . next: 0x7ffe163275e8
post create ll mut ptr: 0x7ffe16327560, post create ll mut ptr next 0x7ffe163275e8
before pointer head: 0x7ffe16327560. before pointer next 0x7ffe16327560
For the first 2 elements the code behaves as expected: it creates an element with null pointer as its next element. Here is the state of things after adding second element:
{
head: {
elem: 64,
next: {
elem: 32,
next: nullptr
}
}
}
64 -> 32 -> null
When the third element is added, things become weird and the linked list transforms into something like this:
{
head: {
elem: 72,
next: {
elem: 72,
next: {
elem: 72,
next: ...
}
}
}
}
72 -> 72 -> 72 -> ...
It seems that the linked list element's next field starts pointing at the element itself.
I have debugged the LinkedListElement::new method and found that the proper element should get returned from it:
{
elem: 72,
next: {
elem: 64,
next: {
elem: 32,
next: nullptr
}
}
}
For some reason, immediately after it is returned to LinkedList::insert method, even before self.head is reassigned, the contents of LinkedList self becomes "corrupted".
I know using raw pointers in Rust is not idiomatic but I still want to learn them.
Congratulations, you have successfully proven why Rust needs to exist in the first place: programmers write memory-unsafe code.
First, please read why this is disallowed when using safe Rust:
Is there any way to return a reference to a variable created in a function?
TL;DR: the memory address of LinkedListElement changes when it's moved. A move occurs when a value is returned from a function (among other times). By using a raw pointer, you've subverted the borrow checker and get no useful feedback from the compiler.
Second, please read Learning Rust With Entirely Too Many Linked Lists. For whatever reason, programmers think that linked lists are "easy" and a good way to learn a language. This is generally not true in Rust, where memory safety is paramount.
TL;DR: you can use a Box to allocate memory on the heap. This memory address will not change when the pointer to it is moved. You will need to ensure that you appropriately free the pointer when your linked list goes out of scope to prevent memory leaks.
See also:
How to copy a raw pointer when implementing a linked list in Rust?
Box::into_raw / Box::from_raw
NonNull

How do you replace the value of a mutable variable by taking ownership of it?

I am working with a LinkedList and I want to remove all elements which do not pass a test. However, I am running into the error cannot move out of borrowed content.
From what I understand, this is because I am working with &mut self, so I do not have the right to invalidate (i.e. move) one of the contained values even for a moment to construct a new list of its values.
In C++/Java, I would simply iterate the list and remove any elements which match a criteria. As there is no remove that I have yet found, I have interpreted it as an iterate, filter, and collect.
The goal is to avoid creating a temporary list, cloning values, and needing take self and return a "new" object. I have constructed an example which produces the same error. Playground.
use std::collections::LinkedList;
#[derive(Debug)]
struct Example {
list: LinkedList<i8>,
// Other stuff here
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(-5);
list.push_back(3);
list.push_back(-1);
list.push_back(6);
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<i8> {
self.list.iter()
.filter(|&&x| x > 0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.into_iter()
.filter(|&x| x > 0)
.collect()
}
}
fn main() {
let mut e = Example::default();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}
In my actual case, I cannot simply consume the wrapping object because it needs to be referenced from different places and contains other important values.
In my research, I found some unsafe code which leads me to question if a safe function could be constructed to perform this action in a similar way to std::mem::replace.
You can std::mem::swap your field with a temp, and then replace it with your modified list like this. The big downside is the creation of the new LinkedList. I don't know how expensive that is.
pub fn remove_negative(&mut self) {
let mut temp = LinkedList::new();
std::mem::swap(&mut temp, &mut self.list);
self.list = temp.into_iter()
.filter(|&x| x > 0)
.collect();
}
If the goal is not clone you may use a reference-counting pointer: the clone method on Rc increments the reference counter.
use std::collections::LinkedList;
use std::rc::Rc;
#[derive(Debug)]
struct Example {
list: LinkedList<Rc<i8>>,
// ...
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(Rc::new(-5));
list.push_back(Rc::new(3));
list.push_back(Rc::new(-1));
list.push_back(Rc::new(6));
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<Rc<i8>> {
self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
}
fn main() {
let mut e = Example::default();
e.remove_negative();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}

Trait is not implemented for the type `&A` when passing an array of pairs to a function

I am trying to write the function set which calls the Rust LMDB library (docs), and an example I'm working off of.
I can't for the life of me get this to work. Here is my current attempt:
fn main() {
let env = getenv("duperdb");
let dbhandle = get_dbhandle("", &env);
let txn = new_transaction(&env);
let vec = vec![("foo", "another text"), ("bar", "and another")];
set(&dbhandle, &env, &vec);
let reader = env.get_reader().unwrap();
let db = reader.bind(&dbhandle);
let note = db.get::<&str>("foo").unwrap();
println!("NOTE: {}", note);
}
Where set is defined as:
pub fn set<A: ToMdbValue, B: ToMdbValue>(
handle: &DbHandle,
env: &Environment,
pairs: &Vec<(&A, &B)>) -> () {
let txn = new_transaction(&env);
{
let db = txn.bind(&handle);
for &(id, note) in pairs.iter() {
db.set(&id, &note).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}
This spits out the following error:
src/db/wrapper.rs:28:20: 28:23 error: the trait `lmdb::traits::ToMdbValue` is not implemented for the type `&A` [E0277]
src/db/wrapper.rs:28 db.set(&id, &note).unwrap();
^~~
I also tried db.set(id, note).unwrap();, but this time I get:
src/main.rs:13:5: 13:8 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
src/main.rs:13 set(&dbhandle, &env, &vec);
^~~
src/main.rs:13:5: 13:8 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:13:5: 13:8 note: `str` does not have a constant size known at compile-time
src/main.rs:13:5: 13:8 note: required by `dupernote::db::wrapper::set`
src/main.rs:13:5: 13:8 error: the trait `lmdb_rs::traits::ToMdbValue` is not implemented for the type `str` [E0277]
src/main.rs:13 set(&dbhandle, &env, &vec);
^~~
I also tried stuff like:
for (id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
But that doesn't work either... I don't fully understand why. Doesn't id and note have type &str, not str?
Here's an MCVE of your problem:
trait Example {}
impl Example for i32 {}
fn library_call<T>(value: T)
where T: Example,
{}
fn user_call<T>(values: &[T])
where T: Example,
{
for i in values {
library_call(i);
}
}
fn main() {
let values = vec![1, 2, 3];
user_call(&values);
}
With the error:
error: the trait `Example` is not implemented for the type `&T` [E0277]
library_call(i);
^~~~~~~~~~~~
The error message is exactly correct - Example is not implemented for &T, it's only guaranteed to be implemented for T. &T and T are different types.
Instead, you need to indicate that a reference to the generic type implements the trait you need:
fn user_call<T>(values: &[T])
where for <'a> &'a T: Example,
And then you need to make sure that a reference to the concrete type actually implements the trait:
impl<'a> Example for &'a i32 {}
Or a broader version:
impl<'a, T> Example for &'a T
where T: Example
{}
See also When should I not implement a trait for references to implementors of that trait?
The definition of the function that gives you an error (if I'm reading the docs right):
fn set(&self, key: &ToMdbValue, value: &ToMdbValue) -> MdbResult<()>
key must be a reference to a trait object. You are trying to pass a reference to a generic type implmementing ToMdbValue.
https://doc.rust-lang.org/book/trait-objects.html
I can't verify but this should work:
pub fn set(handle: &DbHandle, env: &Environment, pairs: &Vec<(&ToMdbValue, &ToMdbValue)>) -> () {
let txn = new_transaction(&env);
{
let db = txn.bind(&handle);
for &(id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}
Other things: you may want to work with boxed trait objects Box<ToMdbValue>. The link above explains it. You should pass a &[YourType] rather than &Vec<[YourType]>.
I managed to get it working. I'm not sure how kosher this solution is, but I'll post it.
So now, in main(), I do the following (example with an (int, string) kv pair):
let k = 1;
let val = "hello there";
let vec = vec![(&k, &val)];
set(&dbhandle, &env, &vec);
I had to declare them separately since vec![(&1, &"hello there")] threw an error of the form borrowed value does not live long enough.
set now looks like this:
pub fn set<A, B>(handle: &DbHandle, env: &Environment, pairs: &Vec<(&A, &B)>)
-> ()
where A: ToMdbValue,
B: ToMdbValue {
let txn = new_transaction(&env);
{
let db = txn.bind(&handle);
for &(id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}

What does "Overflow evaluating the requirement" mean and how can I fix it?

I'm running into what is potentially a compiler bug. However, I don't understand the issue well enough to port the proposed solution to my own code. Here's a stripped-down version of my code:
struct Node {
pub children: Vec<Node>,
}
fn map_nodes<F, R>(f: F, n: &Node) -> Vec<R>
where
F: Fn(&Node) -> R,
{
let mut v: Vec<R> = Vec::new();
v.push(f(n));
v.extend(n.children.iter().flat_map(|child| map_nodes(&f, &child)));
v
}
fn main() {
let node = Node {
children: vec![Node { children: vec![] }, Node { children: vec![] }],
};
println!("Node lengths: {:?}", map_nodes(|n| n.children.len(), &node));
}
Specifically the error for this code is:
error[E0275]: overflow evaluating the requirement `[closure#src/main.rs:22:46: 22:66]: std::ops::Fn<(&Node,)>`
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `std::ops::Fn<(&Node,)>` for `&[closure#src/main.rs:22:46: 22:66]`
= note: required because of the requirements on the impl of `std::ops::Fn<(&Node,)>` for `&&[closure#src/main.rs:22:46: 22:66]`
# ... this continues for many lines ...
The problem is an incompatibility, (which I'll show how to resolve) between unique closure types, how generics are instantiated when Rust is compiled, and a recursive use of the closure.
fn map_nodes<F, R>(f: F, n: &Node) -> Vec<R>
where
F: Fn(&Node) -> R,
Each recursive call instantiates a new version of this function, with a new type inserted for F. In this case, the map_nodes receives F and passes on &F, and it creates an infinite series of new map_nodes specializations that would need to be compiled.
What you can do instead is use a concrete closure type by using a reference to a Fn trait object:
fn map_nodes<R>(f: &Fn(&Node) -> R, n: &Node) -> Vec<R>
This would require inserting a & before the lambda expression where the closure is used: map_nodes(&|n| n.children.len(), &node).
If you don't want to burden your public API with this difference, then you can use an internal wrapper for your recursive function instead:
fn map_nodes<F, R>(f: F, n: &Node) -> Vec<R>
where
F: Fn(&Node) -> R,
{
fn map_nodes_inner<R>(f: &Fn(&Node) -> R, n: &Node) -> Vec<R> {
let mut v: Vec<R> = Vec::new();
v.push(f(n));
v.extend(n.children.iter().flat_map(|child| map_nodes_inner(f, &child)));
v
}
map_nodes_inner(&f, n)
}
I don't claim to fully understand the problem, but it looks like an issue with resolving a type parameter. For example, what does F correspond to? At the first level, it is the closure. At the next level, it's a reference to that closure. At the next level, it's a reference to the reference of the closure.
My guess is that this is happening because of inlining, and basically it has hit an infinite recursion.
You can fix it by passing a reference to your closure instead:
struct Node {
pub children: Vec<Node>,
}
fn map_nodes<F, R>(f: &F, n: &Node) -> Vec<R>
where
F: Fn(&Node) -> R,
{
let mut v = Vec::new();
let z: R = f(n);
v.push(z);
v.extend(n.children.iter().flat_map(|child| map_nodes(f, &child)));
v
}
fn main() {
let node = Node {
children: vec![Node { children: vec![] }, Node { children: vec![] }],
};
println!(
"Node lengths: {:?}",
map_nodes(&|n| n.children.len(), &node)
);
}

Resources