user1350184
user1350184

Reputation:

Mutable reference to an item using 'find' in Rust

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

Answers (1)

loganfsmyth
loganfsmyth

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

Related Questions