Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Mutate an object which was taken from a vector in Rust

I have trouble solving an obvious simple problem.

Basically I want to push an instance of a structure to a vector to get it out later and to modify the object by calling a function implemented for the structure.

To simplify the case, I created the following test code, which reflects in my opinion to the same problem.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    let mut strings = Vec::new();
    strings.push("Hello".to_string());
    let string_option = strings.last();
    let string = string_option.unwrap();
    string.shrink_to(1);

This has the compile error

error[E0596]: cannot borrow `*string` as mutable, as it is behind a `&` reference
  --> src/main.rs:89:5
   |
88 |     let string = string_option.unwrap();
   |         ------ help: consider changing this to be a mutable reference: `&mut String`
89 |     string.shrink_to(1);
   |     ^^^^^^^^^^^^^^^^^^^ `string` is a `&` reference, so the data it refers to cannot be borrowed as mutable

Then I tried sheer endless variants like

    let mut strings = Vec::new();
    strings.push("Hello".to_string());
    let string_option = strings.last().as_mut();
    let string = string_option.unwrap();
    string.shrink_to(1);

… or …

    let mut strings = Vec::new();
    strings.push("Hello".to_string());
    let string_option = strings.last().as_deref_mut();
    let string = string_option.unwrap();
    string.shrink_to(1);

Actually the code shown above is a simplification from this code, which I originally wanted to do.

struct Bar {
    data: Vec<String>
}

impl Bar {
    fn shrink_first(&mut self) {

        let s_opt = self.data.last().as_mut();  // s_opt is of type Option<&mut &String>

        let s = s_opt.unwrap(); // s is of type &mut & String
        s.shrink_to(1);
    }
}

The code above brings the following errors …

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:67:21
   |
67 |         let s_opt = self.data.last().as_mut();  // s_opt is of type Option<&mut &String>
   |                     ^^^^^^^^^^^^^^^^         - temporary value is freed at the end of this statement
   |                     |
   |                     creates a temporary which is freed while still in use
68 |
69 |         let s = s_opt.unwrap(); // s is of type &mut & String
   |                 ----- borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value

error[E0596]: cannot borrow `**s` as mutable, as it is behind a `&` reference
  --> src/main.rs:70:9
   |
70 |         s.shrink_to(1);
   |         ^^^^^^^^^^^^^^ cannot borrow as mutable

But in my opinion it always has the same root causes, but I have not figured out what to do.

>Solution :

Simply change strings.last() to strings.last_mut().

The last() method returns a standard (immutable) reference (to be more precise, Option<&T>).

To be able to mutate the last String in the vector, you need to get a mutable reference via last_mut().

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading