Recursive structs error lifetime (cannot infer an appropriate lifetime for lifetime parameter in function call... [E0495]) [duplicate] - recursion

This question already has an answer here:
What lifetimes do I use to create Rust structs that reference each other cyclically?
(1 answer)
Closed 6 years ago.
I can't figure out the lifetime parameters for this code. Everything I try usually results in a compiler error:
consider using an explicit lifetime parameter as shown
or something like
in type &'ent Entity<'a, 'ent>, reference has a longer lifetime than the data it references.
Entity, Reference are simplified versions to keep this example minimal.
struct Entity<'a> {
id: i32,
name: &'a str,
references: Option<Vec<Reference<'a>>>,
}
struct Reference<'a> {
entity: &'a Entity<'a>,
}
fn main() {
let mut ents: Vec<Entity> = vec![Entity {
id: 0,
name: "Zero",
references: None,
},
Entity {
id: 1,
name: "One",
references: None,
},
Entity {
id: 2,
name: "Two",
references: None,
},
Entity {
id: 3,
name: "Three",
references: None,
}];
let references_ents_id = vec![vec![3, 1, 2], vec![1], vec![0, 3], vec![3, 0]];
create_references(&references_ents_id, &mut ents);
}
fn create_references(refs_id: &Vec<Vec<i32>>, ents_vec: &mut Vec<Entity>) {
for (id_ent, references) in refs_id.iter().enumerate() {
let mut references_of_ent: Vec<Reference> = vec![];
for id_ent in references {
references_of_ent.push(Reference {
entity: ents_vec.iter().find(|ent| ent.id == *id_ent).unwrap(),
});
}
ents_vec[id_ent].references = Some(references_of_ent);
}
}
Rust Playground

I was looking in the wrong direction. And so, I found a solution, but unfortunately it is not safe.
You can implement it using Rc and Weak to allow shared ownership of nodes, although this approach pays the cost of memory management.
You can implement it using unsafe code using raw pointers. This will be more efficient, but bypasses Rust’s safety guarantees.
Using borrowed references with UnsafeCell.
Rust FAQ
Other answer on SO
Example of implementation unsafe version with raw pointers:
struct Entity<'a> {
id: i32,
name: &'a str,
references: Option<Vec<Reference<'a>>>,
}
struct Reference<'a> {
entity: *const Entity<'a>,
}
Rust Playground: https://play.rust-lang.org/?gist=8237d8cb80a681c981a85610104f2e5c&version=stable&backtrace=0

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

How to design a Map which can be sorted based on one of the values?

Why this question exists?
I am writing rabbithole-rs, which is a JSON:API implementation based on Rust.
But while designing the sorting/pagination features, I meet a big problem on on designing the attribute fields.
Intro JSON:API soring/pagination briefly
There is a attributes fields in JSON:API's resource object, which is a HashMap<String, serde_json::Value> or HashMap<String, Box<Any>>,
where the key is attribute name, and the value is the attribute's value.
And Vec<Resource> object has a sort(attribute_name: &str) method, which can sort a bunch of Resource based on one of the attribute.
A brief layout of Resource
pub struct Resource {
pub ty: String, // The type of `Resource`, `sort` method can only effect on the same type of resources
pub id: String, // Every `Resource` has an unique id
pub attr1: dyn Ord + Serialize + Deserialize,
... <more attrs>
}
Where:
Each attr should implement at least three traits:
Ord to compare
Serialize to convert into serde_json::Value
Deserialize to convert from serde_json::Value
What the problem is?
When getting a Resource, I have to extract all of the attribute fields and put them into a HashMap, like:
HashMap<String, serde_json::Value> or HashMap<String, Box<Any>>.
But both of them lose the trait info of the attributes, so I cannot compare two attribute item with the same name.
A brief demo, please!
Sure! Here you go!
#[macro_use]
extern crate serde_derive;
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::collections::HashMap;
/// This is a struct field
#[derive(Debug, Serialize, Deserialize, Ord, PartialOrd, PartialEq, Eq)]
pub struct Name {
pub first_name: String,
pub last_name: String,
}
/// Resource object
#[derive(Debug, Serialize, Deserialize, Ord, PartialOrd, PartialEq, Eq)]
pub struct Resource {
pub ty: String,
pub id: String,
pub age: i32, // attr 1
pub name: Name, // another attr
}
fn main() {
let item1 = Resource {
ty: "human".into(),
id: "id1".to_string(),
age: 1,
name: Name {
first_name: "first1".to_string(),
last_name: "last1".to_string(),
},
};
// **This is the first attributes HashMap**
let mut map_item1: HashMap<&str, (&str, Box<dyn Any>)> = Default::default();
map_item1.insert("age", ("i32", Box::new(item1.age)));
map_item1.insert("name", ("Name", Box::new(item1.name)));
let item2 = Resource {
ty: "human".into(),
id: "id2".to_string(),
age: 2,
name: Name {
first_name: "first2".to_string(),
last_name: "last2".to_string(),
},
};
// **This is the second attributes HashMap**
let mut map_item2: HashMap<&str, (&str, Box<dyn Any>)> = Default::default();
map_item2.insert("age", ("i32", Box::new(item2.age)));
map_item2.insert("name", ("Name", Box::new(item2.name)));
// TODO: NEED TO BE IMPLEMENTED
for k in map_item1.keys() {
println!(
"key: {key}, item1.{key} < item2.{key}? {res}",
key = k,
res = map_item1.get(k).unwrap().1.cmp(map_item2.get(k).unwrap().1)
)
}
}

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

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(_) => (),
}
}

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

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

Resources