Reputation:
How can I get a mutable reference to an item found in a vector?
I've tried the following which works if I don't make the iterator mutable using .iter()
:
fn main() {
let mut vec = vec![1, 2, 3, 4];
let mut wrong = -1;
let working = match vec.iter().find(|&c| *c == 2) {
Some(c) => c,
None => &wrong
};
println!("Result: {}", working);
}
But when I try to get a mutable reference using a mutable iterator .iter_mut()
,
fn main() {
let mut vec = vec![1, 2, 3, 4];
let mut wrong = -1;
let mut error = match vec.iter_mut().find(|&c| *c == 2) {
Some(c) => c,
None => &mut wrong
};
println!("Result: {}", error);
}
I get the following error:
error[E0507]: cannot move out of borrowed content --> src/main.rs:5:48 | 5 | let mut error = match vec.iter_mut().find(|&c| *c == 2) { | ^- | || | |hint: to prevent move, use `ref c` or `ref mut c` | cannot move out of borrowed content
I also tried to make the type in the closure mutable with |&mut c|
but that gives the following error:
error[E0308]: mismatched types --> src/main.rs:5:48 | 5 | let mut error = match vec.iter_mut().find(|&mut c| *c == 2) { | ^^^^^^ types differ in mutability | = note: expected type `&&mut {integer}` found type `&mut _` = help: did you mean `mut c: &&&mut {integer}`?
Upvotes: 24
Views: 6114
Reputation: 161517
Rust's .find
passes the callback the type &Self::Item
, and since you are using .iter_mut()
, you've created an iterator where each item is &mut T
. That means the type passed to your find
callback is &&mut T
. To get that to typecheck, you can do either
vec.iter_mut().find(|&&mut c| c == 2)
or
vec.iter_mut().find(|c| **c == 2)
with the second one being preferable.
The error you are getting is because the middle-ground you've chosen by using &c
would set c
to a value of &mut T
, and one of Rust's big rules is that multiple things can't own a mutable reference to an item at the same time. Your non-mutable case works because you are allowed to have multiple immutable references to an item.
Upvotes: 22