Reputation: 67
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.
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`.
Upvotes: 1
Views: 646
Reputation: 1
// Expected output:
// vec0 has length 3, with contents `[22, 44, 66]`
// vec1 has length 4, with contents `[22, 44, 66, 88]`
right should be:
fn main() {
let mut vec0 = Vec::new();
let mut vec1 = fill_vec(&mut vec0);
println!("{} has length {}, with contents: `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {}, with contents `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: &mut Vec<i32>) -> Vec<i32> {
vec.push(22);
vec.push(44);
vec.push(66);
vec.to_vec()
}
Upvotes: -1
Reputation: 1
Because this question's expectation is below:
// Expected output:
// vec0 has length 3 content `[22, 44, 66]`
// vec1 has length 4 content `[22, 44, 66, 88]`
So I think below is a better solution.
let vec0 = Vec::new();
let vec0 = fill_vec(vec0);
// Do not move the following line!
let mut vec1 = vec0.clone();
Upvotes: 0
Reputation: 1455
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.
Upvotes: 2