'How to avoid "move occurs because `v` has type `Vec<char>`, which does not implement the `Copy` trait" within loop
It appears that a prohibited borrow is occurring here but I am not seeing a way around it to do what I'd need to do. It looks like the problem occurs when after setting the mut value within the loop I then try to save it into another Vec. Is there a clean way to get around this or a way to show this move to the compiler so I won't get the error? I'll include the error below the code snippet:
let mut result: Vec<String> = vec![];
let mut v = vec![];
for idx in 0..board.spaces.len() {
let c: char = match board.count_at(idx as u32) {
0 => ' ',
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
_ => 'F'
};
v.push(c);
if idx as u32 + 1 % board.width == 0 {
result.push(v.into_iter().collect());
v.clear();
}
}
Error:
error[E0382]: borrow of moved value: `v`
--> src/lib.rs:41:9
|
26 | let mut v = vec![];
| ----- move occurs because `v` has type `Vec<char>`, which does not implement the `Copy` trait
...
41 | v.push(c);
| ^^^^^^^^^ value borrowed here after move
...
44 | result.push(v.into_iter().collect());
| ----------- `v` moved due to this method call, in previous iteration of loop
|
note: this function takes ownership of the receiver `self`, which moves `v`
Solution 1:[1]
The reason your code doesn't work is because .into_iter() consumes the Vec and it can no longer be used later in the program. You can fix that by doing:
result.push(v.iter().clone().collect());
but I would instead hold the temporary data in a String and push a clone of it into the Vec:
let mut result: Vec<String> = vec![];
let mut s = String::new();
for idx in 0..board.spaces.len() {
let c: char = match board.count_at(idx as u32) {
0 => ' ',
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
_ => 'F'
};
s.push(c);
if idx as u32 + 1 % board.width == 0 {
result.push(s.clone());
s.clear();
}
}
Solution 2:[2]
You can use Vec::append() for "empty myself, pass all elements to a new vector":
let mut result: Vec<String> = vec![];
let mut v = vec![];
for idx in 0..board.spaces.len() {
let c: char = match board.count_at(idx as u32) {
0 => ' ',
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
_ => 'F'
};
v.push(c);
if idx as u32 + 1 % board.width == 0 {
let mut s = Vec::new();
s.append(&mut v); // Pass all elements from `v` to `s`.
result.push(s.into_iter().collect());
}
}
You can also use String directly and push characters with push(), but since String doesn't include an append method you can use std::mem::take():
let mut result: Vec<String> = vec![];
let mut v = String::new();
for idx in 0..board.spaces.len() {
let c: char = match board.count_at(idx as u32) {
0 => ' ',
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
_ => 'F'
};
v.push(c);
if idx as u32 + 1 % board.width == 0 {
result.push(std::mem::take(&mut v));
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dogbert |
| Solution 2 | Chayim Friedman |
