Search code examples
rustvectorlifetime

Borrow error when I try to modify last element of a vector


I am trying to modify a Vec<i32> by doing thing[thing.len() - 1] = other_thing;. I get an error telling me that I borrowed first a mutable reference, then an immutable one. I could not find a workaround. How to modify last element of a vector in rust. Working example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a092f6778df0290de7cee1f2321bf175


Solution

  • You can't borrow the same variable as mutable and immutable at the same time.

    When you are trying to get length of vector, this is where immutable borrowing happens and panics (because at the same time you are trying to change it's content, eg. mutable borrowing)

    You can do it in multiple ways. Let's assume you have a vector with 2 slices

    let mut thing = vec![[1, 2], [3, 4]];
    

    First, with calculating and getting last item from vector manually (as you did in your version)

    let len = thing.len(); // immutable borrow use
    thing[len - 1][1] = 20; // mutable borrow use
    

    But more idiomatic way of doing this is to use methods provided by slice/vec and map over returned Option

    To get the last item we can use last_mut (which will return Option) and map on that Option to get last item of nested slice, and change it's value to 20

    // Set vector's last slice's value at index 1 to 20
    thing.last_mut().map(|s| s[1] = 20);
    // Set vector's last slice's last value to 20
    // In our case this is the same as previous one
    thing.last_mut().map(|s| s.last_mut().map(|i| *i = 20));
    
    assert_eq!(vec![[1, 2], [3, 20]], thing);