Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutable reference to an item using 'find' in Rust

Tags:

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}`?
like image 459
tversteeg Avatar asked Jan 31 '18 20:01

tversteeg


People also ask

What is a mutable reference Rust?

Back to Rust. A mutable reference is a borrow to any type mut T , allowing mutation of T through that reference. The below code illustrates the example of a mutable variable and then mutating its value through a mutable reference ref_i .

What is a Vec in Rust?

Vector is a module in Rust that provides the container space to store values. It is a contiguous resizable array type, with heap-allocated contents. It is denoted by Vec<T>. Vectors in Rust have O(1) indexing and push and pop operations in vector also take O(1) complexity.

What is reference in Rust?

A reference of a variable is a pointer that leads to that variable. Rust uses the concept of ownership, which is associated with how references are used.

Are references mutable C++?

References can only be assigned when constructing an object, and cannot be modified thereafter. Thus making them mutable would have no meaning, which is why the standard disallows it.

How to get the value of a referent in rust?

And to get the value of the referent, you'd use the * operator: All the values and references created above were immutable, which is the default in Rust. If you want to change the value through a reference, create a mutable reference.

What is mutable reference in rust?

Rust supports mutable references which means we can change the value it references if it’s a mutable variable. There are some restrictions on how we use mutable references. You can have only one mutable reference to a particular value in a particular scope to prevent data races

Can a mutable reference change an immutable value?

If the compiler had allowed this, a mutable reference ( m) could change an immutable value ( x ). Such changes in an immutable value would have been confusing. Let's try the fix suggested by the error message:

What is the 'mutable references' lesson?

The "Mutable References" Lesson is part of the full, The Rust Programming Language course featured in this preview video. Here's what you'd learn in this lesson:


1 Answers

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.

like image 163
loganfsmyth Avatar answered Oct 06 '22 13:10

loganfsmyth