This code causes a error. It seems reasonable, because the ownership has moved:
fn main() {
let mut arr = vec![1, 2];
let mut arr2 = vec![2, 6];
arr = arr2;
arr2[1] = 2;
}
error[E0382]: borrow of moved value: `arr2`
--> src/main.rs:5:5
|
3 | let mut arr2 = vec![2, 6];
| -------- move occurs because `arr2` has type `Vec<i32>`, which does not implement the `Copy` trait
4 | arr = arr2;
| ---- value moved here
5 | arr2[1] = 2;
| ^^^^ value borrowed here after move
This code won't cause an error:
fn main() {
let mut arr = [1, 2];
let mut arr2 = [2, 4];
arr = arr2;
arr2[1] = 2;
}
This will cause an error:
fn main() {
let mut arr = ["1".to_string(), "2".to_string()];
let mut arr2 = ["2".to_string(), "4".to_string()];
arr = arr2;
arr2[1] = "2".to_string();
}
error[E0382]: use of moved value: `arr2`
--> src/main.rs:5:5
|
3 | let mut arr2 = ["2".to_string(), "4".to_string()];
| -------- move occurs because `arr2` has type `[String; 2]`, which does not implement the `Copy` trait
4 | arr = arr2;
| ---- value moved here
5 | arr2[1] = "2".to_string();
| ^^^^^^^ value used here after move
This works fine...
fn main() {
let mut arr = ["1", "2"];
let mut arr2 = ["2", "4"];
arr = arr2;
arr2[1] = "2";
}
I am completely confused.
In Rust all types fall into one of two categories:
copy-semantic (if it implements the Copy-trait)
move-semantic (if it does not implement the Copy-trait)
These semantics are implicitly employed by Rust whenever you e.g. assign a value to a variable. You can't choose it at the assignment. Instead, it depends only on the type in question. Therefore, whether a in the example below is moved or copied, depends entirely on what T is:
let a: T = /* some value */;
let b = a; // move or copy?
Also notice, that generic types are rather a set of similar types, than a single type by themselves (i.e. it is not a concrete type). For instance, you can't tell whether [T;2] is Copy or not, since it is not a concrete type (would need to know T first). Thus, [&str;2] and [String;2] are two totally different concrete types, and consequently one can be Copy and the other not.
To further elaborate, a concrete type can only be Copy if all constituting types are Copy. For instance, arrays [T;2] might be Copy (if T is too), Vec may never be Copy (independent of T).
So in your examples, when it does not compile due to move-semantics, you either have a Vec that is not Copy or String that is not, and any combinations with them can not be Copy either. Only if you combine Copy-types (arrays, ints, &str) you get copy-semantics, and your examples compile.
Also, this not an issue about ownership, because if you have copy-semantics you can just generate new values (by coping them) wherever you need, which gives you (fresh) ownership of these new values.
Couple of things here. First of all you are not changing the ownership in the working examples. You are merely borrowing their values. The difference in your not working examples is that in them you are actually changing the ownership.
As #eggyal correctly pointed out String and Vec don't implement Copy and that's important because Copy is used automatically when assigning another variable to a new variable. and in your working examples you have i32 (default for numeric types) and &str(also known as a string slice) which both implement Copy.
Every string literal is initially a &str and not a String. The .to_string() method in your example converts a &str into a String. If you want more in-depth information about the differences between &str and String I suggest you either check this answer or read an article about it but what's most important in your case is that string slices point to a read-only portion of the memory making them effectively immutable and therefore safe for copying.
The compiler nowadays is so good that it tells you the entire story. I compiled your code and got this wonderful error message:
|
18 | let mut a = vec![2, 4];
| ----- move occurs because `a` has type `Vec<i32>`, which does not implement the `Copy` trait
19 | let b = a;
| - value moved here
20 | println!("{:?}", a);
| ^ value borrowed here after move
Related
I am really new to Rust, I am having trouble solving this error, but it only happens if I comment out the while statement , basicly I am asking values from the console and storing it in a HashMap:
use std::collections::HashMap;
use std::io;
fn main() {
let mut customers = HashMap::new();
let mut next_customer = true;
while next_customer {
let mut input_string = String::new();
let mut temp_vec = Vec::with_capacity(3);
let mut vec = Vec::with_capacity(2);
println!("Insert new customer f.e = customer id,name,address:");
io::stdin().read_line(&mut input_string);
input_string = input_string.trim().to_string();
for s in input_string.split(",") {
temp_vec.push(s);
}
vec.push(temp_vec[1]);
vec.push(temp_vec[2]);
let mut key_value = temp_vec[0].parse::<i32>().unwrap();
customers.insert(key_value, vec);
next_customer = false;
}
println!("DONE");
}
The code results in the error
error[E0597]: `input_string` does not live long enough
--> src/main.rs:14:18
|
14 | for s in input_string.split(",") {
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
20 | customers.insert(key_value, vec);
| --------- borrow later used here
21 | next_customer = false;
22 | }
| - `input_string` dropped here while still borrowed
As others have said the problem lies with the lifetime and/or type of the values getting put into the customers map.
customers.insert(key_value, vec);
| --------- borrow later used here
Often this happens when the compiler has decided to give an object a type that you didn't expect. To find out what it's doing you can force the type, and see how it complains. Changing the code to:
let mut customers: HashMap<(),()> = HashMap::new();
Gives us two relevant errors:
20 | customers.insert(key_value, vec);
| ^^^^^^^^^ expected `()`, found `i32`
...
20 | customers.insert(key_value, vec);
| ^^^ expected `()`, found struct `std::vec::Vec`
|
= note: expected unit type `()`
found struct `std::vec::Vec<&str>`
So the type that the compiler wants to give our customers object is HashMap<i32, Vec<&str>>
The problem is that the &str lifetime has got to be inside the block as we don't store the Strings anywhere, and they can't have 'static lifetime since they're user input.
This means we probably want a HashMap<i32,Vec<String>>.
Changing the code to use one of those gives us an error about vec not having the right type: It's getting deduced as a Vec<&str>, but we want a Vec<String>.
We have two options.
Convert the vec to the right type just before we insert it into the map using customers.insert(key_value, vec.iter().map(|s| s.to_string()).collect()). (Though you may want to extract it to a variable for clarity).
Explicitly change the type of vec to Vec<String>
Option 1 "just works". While option 2 leads us down a path of making similar changes closer and closer to the read_line call.
Once you've decided on the fix in option 1, you can remove the manual type annotations that were added to work out the fix, if you find them overly noisy.
The issue is that you are passing around reference to underlying &str values that will get dropped. One way is to take the input string, trim and split it, then clone it going into the other vector.
let temp_vec: Vec<String> = input_string.trim().split(",").map(|t| t.to_string()).collect();
vec.push(temp_vec[1].clone());
vec.push(temp_vec[2].clone());
I have the below Rust program.
fn main() {
let v = vec![100, 32, 57];
for i in v {
println!("{}", i);
}
println!("{:?}", v);
}
When I run it, I get:
error[E0382]: borrow of moved value: `v`
--> src\main.rs:7:22
|
2 | let v = vec![100, 32, 57];
| - move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 | for i in v {
| -
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&v`
...
7 | println!("{:?}", v);
| ^ value borrowed here after move
The error states that there is a move happened at for i in v. But I'm just using the same variable v defined by let v = vec![100, 32, 57]. It's not something like let v2 = v; for i in v2 ..., which moved the value from v to v2. Could anyone help to explain a little bit?
As https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops says,
A for expression is a syntactic construct for looping over elements provided by an implementation of std::iter::IntoIterator.
Vec implements IntoIterator, allowing you to own a Vec instance’s elements by consuming it:
Creates a consuming iterator, that is, one that moves each value out of the vector (from start to end). The vector cannot be used after calling this.
(As the error message notes, the way to fix this is to loop over &v instead of v, borrowing its elements instead of owning them. You can loop for &i in &v to maintain the type of i.)
It might seem unnecessary at a high level for you to own the elements of v, since they’re copyable, but there’s no special implementation allowing that information to be used here. IntoIterator.into_iter() takes self, meaning a for loop always consumes the value being iterated over.
I have the following code:
fn main() {
let mut vec = Vec::new();
vec.push(String::from("Foo"));
let mut row = vec.get_mut(0).unwrap();
row.push('!');
println!("{}", vec[0])
}
It prints out "Foo!", but the compiler tells me:
warning: variable does not need to be mutable
--> src/main.rs:4:9
|
4 | let mut row = vec.get_mut(0).unwrap();
| ----^^^
| |
| help: remove this `mut`
Surprisingly, removing the mut works. This raises a few questions:
Why does this work?
Why doesn't this work when I use vec.get instead of vec.get_mut, regardless of whether I use let or let mut?
Why doesn't vec work in the same way, i.e. when I use let vec = Vec::new(), why can't I call vec.push()?
vec.get_mut(0) returns an Option<&mut String>, so when you unwrap that value you will have a mutable borrow of a String. Remember, that a let statement's left side is using pattern matching, so when your pattern is just a variable name you essentially say match whatever is on the right and call it name. Thus row matches against &mut String so it already is mutable.
Here's a much simpler and more straightforward example to illustrate the case (which you can try in the playground):
fn main() {
let mut x = 55i32;
dbg!(&x);
let y = &mut x; // <-- y's type is `&mut i32`
*y = 12;
dbg!(&x);
}
In Rust by Example, it says:
A ref borrow on the left side of an assignment is equivalent to an & borrow on the right side.
I thought these two for loops would be equivalent:
Compiles successfully:
let mut v2 = vec![1, 2, 3];
for i in &mut v2 {
*i = *i + 1;
}
println!("{:?}", v2);
Does not compile:
let mut v1 = vec![1, 2, 3];
for ref mut i in v1 {
*i = *i + 1;
}
println!("{:?}", v1);
It seems v is moved:
error[E0382]: use of moved value: `v1`
--> src/main.rs:6:22
|
3 | for ref mut i in v1 {
| -- value moved here
...
6 | println!("{:?}", v1);
| ^^ value used here after move
|
= note: move occurs because `v1` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
What you quote from the book is a rule for normal assignments such as those by let. For example:
let x = &42;
let ref x = 42;
But the name binding in a for loop is a bit different:
The value to be looped around is converted into an iterator (<v1 as IntoIterator>::into_iter()) Lets call the result of that it.
Then the it.next() is called repeatedly:
If it returns Some(_) then the value of that is bound to your variable. Just as if you wrote let Some(ref mut i) = it.next() or let Some(mut i) = it.next(). Here is where the ref matters.
If it returns None the loop ends.
So in the for loop case, the ref and the & are not equivalent.
When you use the & at the right side of a loop, it does not change the binding of the variable directly; you just change the type of the object iterated. Then, all comes down to the implementation of IntoIterator for Vec<_> vs that for &Vec<_>.
If you iterate Vec<T>, it takes ownership of the vector and the iteration returns the values themselves. So for i in v1 consumes the vector and the i has the type of the contained values T.
If you iterate &Vec<T>, it borrows the vector and the iteration return pointers to the contained values &T, so in for i in &v1 the type of i is actually a pointer to the values. The same effect can be got with for i in v1.iter().
If you iterate &mut Vec<T>, is just like the previous one but mutable, so the iteration returns values of type &mut T.
The conclusion is that using ref in a for loop is not probably so useful.
I have two versions of a function that are intended to do the same thing.
Version 1 - Works!
pub fn example1() {
// Make a mutable slice
let mut v = [0, 1, 2, 3];
// Make a mutable reference to said slice
let mut v_ref = &mut v[..];
let len = v_ref.len();
// Reduce slice to sub-slice -> np ;)
v_ref = {
// Create sub-slices
let (v_l, v_r) = {
// Involves some edits -> need mut
v_ref.swap(0, len - 1);
{ v_ref }.split_at_mut(len / 2)
};
// Choose slice with which to overwrite
// (involves some non-trivial condition here)
match len % 2 {
0 => v_l,
_ => v_r,
}
};
// And then we do something with v_ref
println!("{:?}", v_ref);
}
Essentially:
We start with a mutable variable, mut v_ref: &mut [i32], containing a mutable reference to a slice
We make two sub-slices from v_ref using split_at_mut*
The variable v_ref is overwritten to hold one of the sub-slices
*(Note - We avoid the problem of having two mutable references by moving v_ref, as opposed to reborrowing, by using an identity block)
(Regarding the intent of the code - this slice reduction is intended to be repeated in a loop; however this detail does not affect the problem)
Version 2 - Fails to compile
Version 2 is nearly identical to version 1, except that the sub-slice creation is moved to its own function:
fn example2_inner(v_ref: &mut [i32]) -> (&mut [i32], &mut [i32]) {
// Recreate len variable in function scope
let len = v_ref.len();
// Same mutation here
v_ref.swap(0, len - 1);
// Same slice split here
v_ref.split_at_mut(len / 2)
}
pub fn example2() {
let mut v = [0, 1, 2, 3];
let mut v_ref = &mut v[..];
let len = v_ref.len();
// This now fails to compile :(
v_ref = {
// Mutating & slice spliting moved to function
let (v_l, v_r) = example2_inner({ v_ref });
match len % 2 {
0 => v_l,
_ => v_r,
}
};
println!("{:?}", v_ref);
}
When I try to build this, I get the following errors:
error[E0506]: cannot assign to `v_ref` because it is borrowed
--> src/lib.rs:19:5
|
19 | / v_ref = {
20 | | // Mutating & slice spliting moved to function
21 | | let (v_l, v_r) = example2_inner({ v_ref });
| | ----- borrow of `v_ref` occurs here
22 | |
... |
26 | | }
27 | | };
| |_____^ assignment to borrowed `v_ref` occurs here
error[E0502]: cannot borrow `v_ref` as immutable because `*v_ref` is also borrowed as mutable
--> src/lib.rs:29:22
|
21 | let (v_l, v_r) = example2_inner({ v_ref });
| ----- mutable borrow occurs here
...
29 | println!("{:?}", v_ref);
| ^^^^^ immutable borrow occurs here
30 | }
| - mutable borrow ends here
Questions
Why don't these two examples compile the same way? Are mutable reference move semantics (i.e., the {vref} from E1) enforced for methods (i.e. split_at_mut), but not functions (i.e., example2_inner)? Why is this the case?
I would like to keep example2_inner as an independent utility function: how would I change Example 2 to accommodate that?
You can fix it like this:
v_ref = {
// move `v_ref` to a new variable which will go out of scope by the end of the block
let r = v_ref;
// Mutating & slice splitting moved to function
let (v_l, v_r) = example2_inner(r);
match len % 2 {
0 => v_l,
_ => v_r,
}
};
The reason is that v_1 and v_2 both are references to v_ref, but these references both outlive the block because they are being returned from it. Then you try to write to v_ref, which the borrow checker doesn't like because there are still these live references around.
Assigning v_ref to a new variable, r, means that v_ref is no longer valid - the variable has been moved. The live references, v_1 and v_2 are now referring to r, which in turn is a reference to v, and which only lives as long as the block. You are now free to write to v_ref because nothing else is referring to it.
Alternatively, you can just update to Rust Edition 2018, or enable non-lexical lifetimes, which can handle this situation.
Why don't these two examples compile the same way? Are mutable
reference move semantics (i.e., the {vref} from E1) enforced for
methods (i.e. split_at_mut), but not functions (i.e., example2_inner)?
Why is this the case?
Actually, it is not about methods vs functions, but about method call syntax vs function call syntax.
Every method call can be translated into the UFCS (Universal Function Call Syntax) which is generally of this form:
<Type as Trait>::method(args);
If we make a naive attempt to translate the call of { v_ref }.split_at_mut(len / 2) into UFCS in version 1, we end up with the same error as in version 2:
<[_]>::split_at_mut({v_ref}, len / 2)
The reason is that the above is equivalent to something which again does not cause v_ref to be moved into the block:
<[_]>::split_at_mut({&mut *v_ref}, len / 2)
What the method syntax actually resolves to is this working variant of the above:
<[_]>::split_at_mut(&mut *{v_ref}, len / 2)
For this variant, the compiler infers that v_ref indeed should be moved into the block, because the compiler realizes that the re-borrowing necessary for the method call is already going to happen on {v_ref}, so it doesn't insert an additional superfluous re-borrow on v_ref.
Now that we know how the method syntax solves your issue implicitly, we have an alternative solution for your issue in version 2:
example2_inner(&mut *{ v_ref });