I am assigning data to properties of a struct, but the following error appears:
error[E0382]: borrow of partially moved value: `super_hero`
--> src/main.rs:16:22
|
13 | for mut chunk in super_hero.description_chunks.unwrap() {
| -------- `super_hero.description_chunks` partially moved due to this method call
...
16 | println!("{:?}", &super_hero);
| ^^^^^^^ value borrowed here after partial move
|
note: this function takes ownership of the receiver `self`, which moves `super_hero.description_chunks`
--> /Users/someuser/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/option.rs:752:25
|
752 | pub const fn unwrap(self) -> T {
| ^^^^
= note: partial move occurs because `super_hero.description_chunks` has type `std::option::Option<Vec<Chunk>>`, which does not implement the `Copy` trait
help: consider calling `.as_ref()` to borrow the type's contents
|
13 | for mut chunk in super_hero.description_chunks.as_ref().unwrap() {
| +++++++++
The following is the code where I am assigning data to properties of a struct:
let super_hero_description = "several years ago.";
let mut super_hero = SuperHero::new(super_hero_description);
super_hero.description_chunks = Option::from(super_hero.get_decription_chunks(DescriptionTypes::NotVillan));
for mut chunk in super_hero.description_chunks.unwrap() {
chunk.data = Option::from(chunk.get_data(DescriptionTypes::NotVillan).await);
}
println!("{:?}", &super_hero);
The error does not happen until I try to print the super_hero at the end.
Oh, and if I follow the recommendation rust gives me
for mut chunk in super_hero.description_chunks.as_ref().unwrap() {
| +++++++++
I end up with another error:
error[E0594]: cannot assign to `chunk.data`, which is behind a `&` reference
--> src/main.rs:14:9
|
13 | for mut subdivision in super_hero.description_chunks.as_ref().unwrap() {
| ------------------------------------- this iterator yields `&` references
14 | chunk.data = Option::from(chunk.get_data()(DescriptionTypes::NotVillan).await);
| ^^^^^^^^^^^^ `chunk` is a `&` reference, so the data it refers to cannot be written
rustc is correct, it just needs a little adjustment: instead of as_ref() use as_mut(), that converts &mut Option<T> to Option<&mut T> instead of &Option<T> to Option<&T>.
The problem is that unwrap() requires an owned Option: see Reference to unwrapped property fails: use of partially moved value: `self`.
Related
This question already has an answer here:
Can I pass the same mutable trait object in multiple iterations of a loop without adding indirection?
(1 answer)
Closed 25 days ago.
Here's some simple code that seems like it should work:
use serde_json;
use std::io::Write;
fn test(writer: &mut dyn Write) {
serde_json::to_writer(writer, "test1").unwrap();
serde_json::to_writer(writer, "test2").unwrap();
}
But it produces the following error:
error[E0382]: use of moved value: `writer`
--> src/main.rs:35:27
|
33 | fn test(writer: &mut dyn Write) {
| ------ move occurs because `writer` has type `&mut dyn std::io::Write`, which does not implement the `Copy` trait
34 | serde_json::to_writer(writer, "test1").unwrap();
| ------ value moved here
35 | serde_json::to_writer(writer, "test2").unwrap();
| ^^^^^^ value used here after move
To get it to work, I have to jump through this hoop:
fn test(writer: &mut dyn Write) {
serde_json::to_writer(&mut *writer, "test1").unwrap();
serde_json::to_writer(writer, "test2").unwrap();
}
What is going on here? Why can I "manually" copy the ref by deref/re-referencing it, but it doesn't implement Copy?
This is specifically something to do with the generic type signature of serde_json::to_writer, because it also works fine with a different function:
fn test(x: &mut dyn Write) {
x.write_all(b"test1").unwrap();
x.write_all(b"test2").unwrap();
}
In Rust &T implements Copy. However, &mut T doesn't. It has to be moved (because of Aliasing NAND Mutability)
In your case writer being a &mut T is moved out into serde_json::to_writer and afterwards the reference is unusable for another call. However, for convenience Rust allows to borrow mutably from a mutable refenrence in simple cases - only if this borrow will die before the original mutable reference is used. This is what you did in your quesion, you may consider it as a "temporary reversable ownership transfer"
Trying to use it in other ways would fail. For example, this one uses the original mutable reference before the the secondary borrow is eliminated.
fn test(writer: &mut dyn Write) {
let mut w = &mut *writer;
serde_json::to_writer(writer, "test1").unwrap();
serde_json::to_writer(w, "test1").unwrap();
}
error[E0505]: cannot move out of `writer` because it is borrowed
--> src/main.rs:6:27
|
5 | let mut w = &mut *writer;
| ------------ borrow of `*writer` occurs here
6 | serde_json::to_writer(writer, "test1").unwrap();
| ^^^^^^ move out of `writer` occurs here
7 | serde_json::to_writer(w, "test1").unwrap();
| - borrow later used here
And this one tries to create multiple temprorary mutable borrows at the same time
fn test(writer: &mut dyn Write) {
let mut w = &mut *writer;
let mut w1 = &mut *writer;
serde_json::to_writer(w, "test1").unwrap();
}
error[E0499]: cannot borrow `*writer` as mutable more than once at a time
--> src/main.rs:6:18
|
5 | let mut w = &mut *writer;
| ------------ first mutable borrow occurs here
6 | let mut w1 = &mut *writer;
| ^^^^^^^^^^^^ second mutable borrow occurs here
7 | serde_json::to_writer(w, "test1").unwrap();
| - first borrow later used here
i am trying Rust by doing the restlings exercices that is a very good approach to start with but there is something that i do not understand.
Exercice: move_semantics2
I understand that in order to initialize vec1 with the content of vec0 without taking the ownership away we have to either clone vec0 or to pass by reference. The issue is that this code, that passes references doesn't seem to work.
I wanna understand why, any idea ?
// move_semantics2.rs
// Make me compile without changing line 13 or moving line 10!
// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(&vec0);
// Do not change the following line!
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: &Vec<i32>) -> &Vec<i32> {
let mut vec = vec;
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
this is the error i am getting :
⚠️ Compiling of exercises/move_semantics/move_semantics2.rs failed! Please try again. Here's the output:
warning: variable does not need to be mutable
--> exercises/move_semantics/move_semantics2.rs:8:9
|
8 | let mut vec1 = fill_vec(&vec0);
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0596]: cannot borrow `*vec1` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:13:5
|
8 | let mut vec1 = fill_vec(&vec0);
| -------- consider changing this binding's type to be: `&mut Vec<i32>`
...
13 | vec1.push(88);
| ^^^^^^^^^^^^^ `vec1` is a `&` reference, so the data it refers to cannot be borrowed as mutable
warning: variable does not need to be mutable
--> exercises/move_semantics/move_semantics2.rs:19:9
|
19 | let mut vec = vec;
| ----^^^
| |
| help: remove this `mut`
error[E0596]: cannot borrow `*vec` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:21:5
|
19 | let mut vec = vec;
| ------- consider changing this binding's type to be: `&mut Vec<i32>`
20 |
21 | vec.push(22);
| ^^^^^^^^^^^^ `vec` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*vec` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:22:5
|
19 | let mut vec = vec;
| ------- consider changing this binding's type to be: `&mut Vec<i32>`
...
22 | vec.push(44);
| ^^^^^^^^^^^^ `vec` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*vec` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:23:5
|
19 | let mut vec = vec;
| ------- consider changing this binding's type to be: `&mut Vec<i32>`
...
23 | vec.push(66);
| ^^^^^^^^^^^^ `vec` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to 4 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0596`.
I think your misconception stems from this line in fill_vec():
let mut vec = vec;
That line is not making a copy of the original vector, instead it tries to make the original immutable reference to the passed in vector mutable, which naturally the compiler does not allow. If your intent was to make a copy of the the passed-in vector, you would want your function to look like this:
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut new_vec = vec.clone();
new_vec.push(22);
new_vec.push(44);
new_vec.push(66);
new_vec
}
Note that this new version uses clone() to copy the original vector, and instead of returning a reference to a vector, it returns a new vector.
I have trouble solving an obvious simple problem.
Basically I want to push an instance of a structure to a vector to get it out later and to modify the object by calling a function implemented for the structure.
To simplify the case, I created the following test code, which reflects in my opinion to the same problem.
let mut strings = Vec::new();
strings.push("Hello".to_string());
let string_option = strings.last();
let string = string_option.unwrap();
string.shrink_to(1);
This has the compile error
error[E0596]: cannot borrow `*string` as mutable, as it is behind a `&` reference
--> src/main.rs:89:5
|
88 | let string = string_option.unwrap();
| ------ help: consider changing this to be a mutable reference: `&mut String`
89 | string.shrink_to(1);
| ^^^^^^^^^^^^^^^^^^^ `string` is a `&` reference, so the data it refers to cannot be borrowed as mutable
Then I tried sheer endless variants like
let mut strings = Vec::new();
strings.push("Hello".to_string());
let string_option = strings.last().as_mut();
let string = string_option.unwrap();
string.shrink_to(1);
... or ...
let mut strings = Vec::new();
strings.push("Hello".to_string());
let string_option = strings.last().as_deref_mut();
let string = string_option.unwrap();
string.shrink_to(1);
Actually the code shown above is a simplification from this code, which I originally wanted to do.
struct Bar {
data: Vec<String>
}
impl Bar {
fn shrink_first(&mut self) {
let s_opt = self.data.last().as_mut(); // s_opt is of type Option<&mut &String>
let s = s_opt.unwrap(); // s is of type &mut & String
s.shrink_to(1);
}
}
The code above brings the following errors ...
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:67:21
|
67 | let s_opt = self.data.last().as_mut(); // s_opt is of type Option<&mut &String>
| ^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
68 |
69 | let s = s_opt.unwrap(); // s is of type &mut & String
| ----- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
error[E0596]: cannot borrow `**s` as mutable, as it is behind a `&` reference
--> src/main.rs:70:9
|
70 | s.shrink_to(1);
| ^^^^^^^^^^^^^^ cannot borrow as mutable
But in my opinion it always has the same root causes, but I have not figured out what to do.
Simply change strings.last() to strings.last_mut().
The last() method returns a standard (immutable) reference (to be more precise, Option<&T>).
To be able to mutate the last String in the vector, you need to get a mutable reference via last_mut().
This is a super contrived example that shows what I want to do; I have a HashMap that I want to push data in to, but I want to do it in a set of threads - the real example is that I'm connecting to a remote service inside the thread::spawn and so I want to have all of it happen in the background as much as possible so it doesn't block the primary thread.
I'm not sure how to refactor my code to allow what I'm wanting to do - any suggestions would be helpful!
let mut item_array : HashMap<i32, i32> = HashMap::new();
let mut array: [i32; 3] = [0, 1, 2];
for item in &array {
thread::spawn(|| {
item_array.insert(*item, *item);
});
}
println!("{:?}", item_array);
The errors I receive are below
error[E0597]: `array` does not live long enough
--> src/main.rs:87:17
|
87 | for item in &array {
| ^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `array` is borrowed for `'static`
...
153 | }
| - `array` dropped here while still borrowed
error[E0499]: cannot borrow `item_array` as mutable more than once at a time
--> src/main.rs:88:23
|
88 | thread::spawn(|| {
| - ^^ mutable borrow starts here in previous iteration of loop
| _________|
| |
89 | | item_array.insert(*item, *item);
| | ---------- borrows occur due to use of `item_array` in closure
90 | | });
| |__________- argument requires that `item_array` is borrowed for `'static`
error[E0373]: closure may outlive the current function, but it borrows `item`, which is owned by the current function
--> src/main.rs:88:23
|
88 | thread::spawn(|| {
| ^^ may outlive borrowed value `item`
89 | item_array.insert(*item, *item);
| ---- `item` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:88:9
|
88 | / thread::spawn(|| {
89 | | item_array.insert(*item, *item);
90 | | });
| |__________^
help: to force the closure to take ownership of `item` (and any other referenced variables), use the `move` keyword
|
88 | thread::spawn(move || {
| ^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `item_array`, which is owned by the current function
--> src/main.rs:88:23
|
88 | thread::spawn(|| {
| ^^ may outlive borrowed value `item_array`
89 | item_array.insert(*item, *item);
| ---------- `item_array` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:88:9
|
88 | / thread::spawn(|| {
89 | | item_array.insert(*item, *item);
90 | | });
| |__________^
help: to force the closure to take ownership of `item_array` (and any other referenced variables), use the `move` keyword
|
88 | thread::spawn(move || {
| ^^^^^^^
error[E0502]: cannot borrow `item_array` as immutable because it is also borrowed as mutable
--> src/main.rs:92:22
|
88 | thread::spawn(|| {
| - -- mutable borrow occurs here
| _________|
| |
89 | | item_array.insert(*item, *item);
| | ---------- first borrow occurs due to use of `item_array` in closure
90 | | });
| |__________- argument requires that `item_array` is borrowed for `'static`
91 | }
92 | println!("{:?}", item_array);
| ^^^^^^^^^^ immutable borrow occurs here
There are two problems here (which are typical problems with multithreaded Rust):
Your thread cannot borrow any data that may outlive it (which, when using std::thread::spawn, is any data1).
Multiple thread cannot borrow the same mutable data.
The first problem is typically solved by:
Copying data instead of referencing it. This is particularly useful for primitive types, such as integers.
Using scoped threads.
Using Arc for thread-safe shared pointer, to ensure that data outlives all threads using it.
Not all are possible in all cases, but I'd recommend the above solutions in that order.
The second problem is typically solved with locks such as Mutex or RwLock, which allows only a single thread to get a mutable reference at a time.
Combining these, I'd solve your example like this:
// mutable data is wrapped in a Mutex
let item_array: Mutex<HashMap<i32, i32>> = Mutex::new(HashMap::new());
// immutable data does not have to be wrapped with scoped threads
let array: [i32; 3] = [0, 1, 2];
// using crossbeam::scope from the crossbeam library, which lets
// us reference variables outside the scope (item_array and array)
crossbeam::scope(|s| {
for item in &array {
// copy item (since it is an integer)
let item = *item;
// explicitly reference item_array, since we'll later need to move this
let item_array_ref = &item_array;
// move item and item_array_ref into the closure (instead of referencing,
// which is by default)
s.spawn(move |_| {
// need to call .lock() to aquire a mutable reference to the HashMap
// will wait until the mutable reference is not used by any other threads
let mut item_array_lock = item_array_ref.lock().unwrap();
item_array_lock.insert(item, item);
});
}
// the scope will persist until all threads spawned inside it (with s.spawn) have completed, blocking the current thread,
// ensuring that any referenced data outlives all the threads
})
.unwrap();
// need to call .lock() here as well to get a reference to the HashMap
println!("{:?}", item_array.lock().unwrap());
Run in playground
1Except when the data has 'static lifetime, i.e. can exist for the entire lifetime of the program.
Here is very simple example of code based on source you have provieded:
use std::collections::HashMap;
use std::thread;
fn main() {
let item_array: HashMap<i32, i32> = HashMap::new();
let array: [i32; 3] = [0, 1, 2];
let mut handles = vec![];
let mutex = std::sync::Mutex::new(item_array);
let arc = std::sync::Arc::new(mutex);
for item in &array {
let item = item.to_owned();
let arc_cloned = std::sync::Arc::clone(&arc);
let th = thread::spawn(move || {
let mut guard = arc_cloned.lock().unwrap();
guard.insert(item, item);
});
handles.push(th);
}
for handle in handles {
handle.join().unwrap();
}
println!("{:?}", arc.lock().unwrap());
}
And you can play it here on rust playground
This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 3 years ago.
I'm trying to use some xcb bindings while trying to learn Rust.
conn.get_setup() only borrows an immutable reference; doesn't that borrow end after the function call ends?
use std::error::Error;
use std::convert::From;
pub struct State<'a> {
conn: xcb::Connection,
screen: xcb::Screen<'a>,
}
impl<'a> State<'a> {
pub fn new() -> Result<State<'a>, Box<dyn Error>> {
let (conn, _) = xcb::Connection::connect(None)?;
let screen = conn.get_setup().roots().next().ok_or::<Box<dyn Error>>(From::from("Couldn't get screen"))?;
Ok(State{conn: conn, screen:screen})
}
}
The compiler gives me
error[E0515]: cannot return value referencing local variable `conn`
--> /.../src/lib.rs:16:4
|
15 | let screen = conn.get_setup().roots().next().ok_or::<Box<dyn Error>>(From::from("Couldn't get screen"))?;
| ---- `conn` is borrowed here
16 | Ok(State{conn: conn, screen:screen})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `conn` because it is borrowed
--> /.../src/lib.rs:16:19
|
12 | impl<'a> State<'a> {
| -- lifetime `'a` defined here
...
15 | let screen = conn.get_setup().roots().next().ok_or::<Box<dyn Error>>(From::from("Couldn't get screen"))?;
| ---- borrow of `conn` occurs here
16 | Ok(State{conn: conn, screen:screen})
| ---------------^^^^-----------------
| | |
| | move out of `conn` occurs here
| returning this value requires that `conn` is borrowed for `'a`
Is there any way to return both conn and state or am I just limited to conn?
There would be a use after free error if you did this:
conn is created, it has no attached lifetime
We borrow conn for 'a, which in and of itself is impossible since I could say the following:
State::<'static>::new()
We move conn out of the function, invalidating any references to it.
So therefore, unless if there's a different way to achieve this in the library you're working with, this won't work as-is. Another name for this is a self-referential struct, so you might want to do some looking into why that doesn't work in rust.