Borrowing problem when inserting struct in HashSet - struct

The code is pretty simple: insert a struct in a HashSet and then try use it. I understand the error I get (value borrowed after move) but I can't get a solution.
use std::collections::HashSet;
#[derive(PartialEq, Hash)]
struct MyStruct {
s: String,
n: i32
}
impl Eq for MyStruct {}
impl MyStruct {
fn to_string(&self) -> String {
format!("[s: {}, n: {}]", self.s, self.n)
}
}
fn main() {
let s1 = MyStruct{ s: "aaa".to_string(), n: 50 };
let s2 = MyStruct{ s: "bbb".to_string(), n: 100 };
println!("s1 = {}", s1.to_string());
let mut set: HashSet<MyStruct> = HashSet::new();
set.insert(s1);
// Here I get the error "Value borrowed after move"...
// How can I use s1 or call its method to_string ?
println!("s1 = {}", s1.to_string());
}
The compiler outputs:
--> src\main.rs:28:24
|
18 | let s1 = MyStruct{ s: "aaa".to_string(), n: 50 };
| -- move occurs because `s1` has type `MyStruct`, which does not implement the `Copy` trait
...
24 | set.insert(s1);
| -- value moved here
...
28 | println!("s1 = {}", s1.to_string());
| ^^ value borrowed here after move
Can you suggest how to store structs in HashSet and continue to use them after the insert?
Thank you

On nightly you can enable hash_set_entry and do:
let s1 = set.get_or_insert(s1);
Which will return a &MyStruct referencing the now-moved value.
Otherwise, as mentioned, you can use an Rc, with the refcounting overhead that entails:
use std::rc::Rc;
let s1 = Rc::new(MyStruct{ s: "aaa".to_string(), n: 50 });
let mut set: HashSet<Rc<MyStruct>> = HashSet::new();
set.insert(s1.clone());
// s1 still works
Or you could make a HashSet<&MyStruct> and insert &s1 instead - of course you'd need to keep s1 alive for the duration of the HashSet.

Related

Rust: How to capture a variable and its referring dependants in a closure?

Code:
#[derive(Clone)]
struct S {
i: i32,
}
fn f1<'a>(s: &'a mut S) -> &'a mut S {
s.i += 1;
s
}
fn k<'a>(v: &'a mut Vec<S>) -> impl FnMut() -> i32 + 'a {
// if I remove this line it's compile
let mut v = v.clone();
let v2: Vec<_> = v.iter_mut().map(|s| f1(s)).map(|s| f1(s)).collect();
move || v2.iter().fold(0, move |accu, value| accu + value.i)
}
fn main() {
let mut v = vec![S { i: 2 }, S { i: 3 }];
let mut f = k(&mut v);
assert_eq!(9, f())
}
The compiler complains with:
error[E0515]: cannot return value referencing local variable `v`
--> src/main.rs:17:5
|
15 | let v2: Vec<_> = v.iter_mut().map(|s| f1(s)).map(|s| f1(s)).collect();
| ------------ `v` is borrowed here
16 |
17 | move || v2.iter().fold(0, move |accu, value| accu + value.i)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
Normally I can capture locally created new variables. But in this case I have dependencies between the clone of v and v2.
I thought the compiler can remember this dependency relation and move both in the closure. But he didn't. How can I solve this problem? (Without removing the line. I have a similar problem where I cannot just remove the line, this is the reduced one.)

Reassign to a higher-scoped mutable referenced variable within a loop

So I'm trying to implement a linked list in Rust to better understand the language and the following is what I came up with.
use std::rc::Rc;
use std::fmt::Debug;
struct Node<T>
where
T: Debug,
{
value: T,
next: Option<Rc<Box<Node<T>>>>,
}
pub struct LinkedList<T>
where
T: Debug,
{
start: Option<Rc<Box<Node<T>>>>,
end: Option<Rc<Box<Node<T>>>>,
}
I managed to implement the insert method, but I'm having trouble implementing the traverse method.
impl<T> LinkedList<T>
where
T: Debug,
{
pub fn insert(&mut self, value: T) {
let node = Rc::new(Box::new(Node { value, next: None }));
match &mut self.end {
None => {
self.start = Some(Rc::clone(&node));
}
Some(ref mut end_node) => {
if let Some(mutable_node) = Rc::get_mut(end_node) {
mutable_node.next = Some(Rc::clone(&node));
}
}
}
self.end = Some(node);
}
pub fn traverse(&mut self) {
let mut ptr = &mut self.start;
while let Some(ref mut node_rc) = &mut ptr {
let inner_ptr = Rc::get_mut(node_rc).unwrap();
*ptr = inner_ptr.next;
}
}
}
In the traverse method I'm trying to do the basic, initialize a pointer at start and keep moving the pointer forward at each iteration of the loop, but the above traverse implementation gives me the following error
rustc: cannot move out of `inner_ptr.next` which is behind a mutable reference
move occurs because `inner_ptr.next` has type `Option<Rc<Box<Node<T>>>>`, which does not implement the `Copy` trait
which made some sense to me, so I tried modifying my code to
ptr = &mut inner_ptr.next;
but now I get a different error stating
|
56 | while let Some(ref mut node_rc) = &mut ptr {
| -------- borrow of `ptr` occurs here
...
59 | ptr = &mut inner_ptr.next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| assignment to borrowed `ptr` occurs here
| borrow later used here
I thought I was getting this error because inner_ptr is dropped at the end of each loop iteration, so I made the following change to the traverse method by having inner_ptr's lifetime to equal ptr's lifetime, like so
pub fn traverse(&mut self) {
let mut ptr = &mut self.start;
let mut inner_ptr: &mut Box<Node<T>>;
while let Some(ref mut node_rc) = &mut ptr {
inner_ptr = Rc::get_mut(node_rc).unwrap();
ptr = &mut inner_ptr.next;
}
}
But, the compiler throws the same error in this case as well. Clearly I'm missing something fundamental here about Rust's borrow mechanism, but I can't figure out what
You're taking a mutable reference of ptr when you should't.
pub fn traverse(&mut self) {
let mut ptr = &mut self.start;
while let Some(ref mut node_rc) = ptr { // don't take a mutable reference here
println!("{:?}", node_rc.value);
let inner_ptr = Rc::get_mut(node_rc).unwrap();
ptr = &mut inner_ptr.next;
}
}
You don't want to take a mutable reference there because you don't want to borrow it which would prevent you from changing it later.
Instead you want to move it and replace it every loop.

Is it possible to flatten Vec<&[u8]> into &[u8] without copying the data?

I want to flatten a vector containing &[u8]:
fn main() {
let x: &[u8] = &b"abc"[..];
let y: &[u8] = &b"def"[..];
let z: Vec<&[u8]> = vec![x, y];
println!("z: {:?}", z);
let z_flat: &[u8] = z.into_iter().flatten().collect();
println!("z_flat: {:?}", z_flat);
}
I get the compiler error:
error[E0277]: a value of type `&[u8]` cannot be built from an iterator over elements of type `&u8`
--> src/main.rs:9:49
|
9 | let z_flat: &[u8] = z.into_iter().flatten().collect();
| ^^^^^^^ value of type `&[u8]` cannot be built from `std::iter::Iterator<Item=&u8>`
|
= help: the trait `FromIterator<&u8>` is not implemented for `&[u8]`
I have also tried the following:
let z_flat: &[u8] = &z.into_iter().map(|x| x.to_vec()).flatten().collect();
Compile error:
error[E0277]: a value of type `[u8]` cannot be built from an iterator over elements of type `u8`
--> src/main.rs:9:70
|
9 | let z_flat: &[u8] = &z.into_iter().map(|x| x.to_vec()).flatten().collect();
| ^^^^^^^ value of type `[u8]` cannot be built from `std::iter::Iterator<Item=u8>`
|
= help: the trait `FromIterator<u8>` is not implemented for `[u8]`
The following does work (playground):
let z_flat: &[u8] = &z.concat();
I am not able to use concat in my real-world application because I am using another struct when retrieving the nested bytes (x and y) and this struct cannot implement Copy (only Clone) because it contains a Vec<u8> field. I have something similar to this (playground):
#[derive(Clone, Debug)]
struct Foo {
Bar: Vec<u8>,
}
impl Foo {
fn baz(&self) -> Vec<u8> {
self.Bar
}
}
fn main() {
let x = Foo { Bar: vec![8u8] };
let y = Foo { Bar: vec![18u8] };
let z: Vec<Foo> = vec![x, y];
println!("z: {:?}", z);
let z_flat = z
.into_iter()
.map(|x| &x.baz()[..])
.collect::<Vec<&[u8]>>()
.concat();
println!("z_flat: {:?}", z_flat);
}
Compile error:
error[E0507]: cannot move out of `self.Bar` which is behind a shared reference
--> src/main.rs:8:9
|
8 | self.Bar
| ^^^^^^^^ move occurs because `self.Bar` has type `Vec<u8>`, which does not implement the `Copy` trait
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:22:18
|
22 | .map(|x| &x.baz()[..])
| ^-------^^^^
| ||
| |temporary value created here
| returns a value referencing data owned by the current function
No, it is not possible. By definition, a slice is one contiguous region of memory. You don't have that to start with, so you can't create a slice.
Your workaround copies everything into one contiguous chunk of memory, which you can then get a slice of. I'd write it something like:
let z: Vec<&[u8]> = vec![b"abc", b"def"];
let z_alloc: Vec<u8> = z.iter().flat_map(|&x| x).copied().collect();
let z_flat: &[u8] = &z_alloc;
println!("z_flat: {:?}", z_flat);
For your larger example:
// fn baz(self) -> Vec<u8>
let z_flat: Vec<u8> = z.into_iter().flat_map(Foo::baz).collect();
// fn baz(&self) -> &[u8]
let z_flat: Vec<u8> = z.iter().flat_map(Foo::baz).copied().collect();
See also:
How to get a slice from an Iterator?

How do I modify the content of a `RefCell<Option<T>>`?

I have an Option<T> that is shared by several structures and that must be mutable. I'm using a RefCell since, as I understand, it is the tool for that job. How do I access (and alter) the content of that Option<T> ?
I tried the following:
use std::cell::RefCell;
#[derive(Debug)]
struct S {
val: i32
}
fn main() {
let rc: RefCell<Option<S>> = RefCell::new(Some(S{val: 0}));
if let Some(ref mut s2) = rc.borrow_mut() {
s2.val += 1;
}
println!("{:?}", rc);
}
But the compiler won't let me do it:
error[E0308]: mismatched types
--> <anon>:10:12
|
10 | if let Some(ref mut s2) = rc.borrow_mut() {
| ^^^^^^^^^^^^^^^^ expected struct `std::cell::RefMut`, found enum `std::option::Option`
|
= note: expected type `std::cell::RefMut<'_, std::option::Option<S>, >`
found type `std::option::Option<_>`
When you borrow_mut the RefCell, you get a RefMut, as the compiler says. To get the value inside it, just use the operator deref_mut:
use std::cell::RefCell;
#[derive(Debug)]
struct S {
val: i32
}
fn main() {
let rc: RefCell<Option<S>> = RefCell::new(Some(S{val: 0}));
if let Some(ref mut s2) = *rc.borrow_mut() { // deref_mut
s2.val += 1;
}
println!("{:?}", rc);
}

Dereferencing boxed struct and moving its field causes it to be moved

Dereferencing a boxed struct and moving its field causes it to be moved, but doing it in another way works just fine. I don't understand the difference between these two pop functions. How does one fail when the other one doesn't?
pub struct Stack<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Stack<T> {
pub fn pop(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
let node = *boxed_node;
self.head = node.next;
node.element
})
}
pub fn pop_causes_error(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
self.head = (*boxed_node).next;
(*boxed_node).element
})
}
}
error[E0382]: use of moved value: `boxed_node`
--> src/main.rs:22:13
|
21 | self.head = (*boxed_node).next;
| ------------------ value moved here
22 | (*boxed_node).element
| ^^^^^^^^^^^^^^^^^^^^^ value used here after move
|
= note: move occurs because `boxed_node.next` has type `std::option::Option<std::boxed::Box<Node<T>>>`, which does not implement the `Copy` trait
You can only move out of a box once:
struct S;
fn main() {
let x = Box::new(S);
let val: S = *x;
let val2: S = *x; // <-- use of moved value: `*x`
}
In the first function, you moved the value out of the box and assigned it to the node variable. This allows you to move different fields out of it. Even if one field is moved, other fields are still available. Equivalent to this:
struct S1 {
a: S2,
b: S2,
}
struct S2;
fn main() {
let x = Box::new(S1 { a: S2, b: S2 });
let tmp: S1 = *x;
let a = tmp.a;
let b = tmp.b;
}
In the second function, you move the value to the temporary (*boxed_node) and then move a field out of it. The temporary value is destroyed immediately after the end of the expression, along with its other fields. The box doesn't have the data anymore, and you don't have a variable to take the other field from. Equivalent to this:
struct S1 {
a: S2,
b: S2,
}
struct S2;
fn main() {
let x = Box::new(S1 { a: S2, b: S2 });
let tmp: S1 = *x;
let a = tmp.a;
let tmp: S1 = *x; // <-- use of moved value: `*x`
let b = tmp.b;
}
Some good news is that non-lexical lifetimes will allow your original code to work:
pub struct Stack<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Stack<T> {
pub fn pop_no_longer_causes_error(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
self.head = (*boxed_node).next;
(*boxed_node).element
})
}
}
NLL enhances the borrow checker to better track the moves of variables.

Resources