5

Here is a really simple attempt at a 2D Vec. I'm trying to add an element to the last entry in the top-level Vec:

fn main() {
    let mut vec_2d = vec![vec![]];
    if let Some(v) = vec_2d.last() {
        v.push(1);
    }
    println!("{:?}", vec_2d);
}

I get this error:

error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference
 --> src/main.rs:4:9
  |
3 |     if let Some(v) = vec_2d.last() {
  |                 - help: consider changing this to be a mutable reference: `&mut std::vec::Vec<i32>`
4 |         v.push(1);
  |         ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable

I've also tried Some(ref v) and Some(ref mut v) with the same results. I can't find any documentation that describes this error specifically. What is the right approach here?

An answer to a similar question recommends something more like Some(&mut v). Then I get these errors:

error[E0308]: mismatched types
 --> src/main.rs:3:17
  |
3 |     if let Some(&mut v) = vec_2d.last() {
  |                 ^^^^^^ types differ in mutability
  |
  = note: expected type `&std::vec::Vec<_>`
             found type `&mut _`
  = help: did you mean `mut v: &&std::vec::Vec<_>`?

If I try Some(&ref mut v) I get:

error[E0596]: cannot borrow data in a `&` reference as mutable
 --> src/main.rs:3:18
  |
3 |     if let Some(&ref mut v) = vec_2d.last() {
  |                  ^^^^^^^^^ cannot borrow as mutable
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
benekastah
  • 5,651
  • 1
  • 35
  • 50

2 Answers2

7

Grab a mutable reference to the last element with last_mut; no need to change patterns.

fn main() {
    let mut vec_2d = vec![vec![]];
    if let Some(v) = vec_2d.last_mut() {
        v.push(1);
    }
    println!("{:?}", vec_2d);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 1
    Some methods can either return a mutable or immutable reference. Those that can usually have the mutable version prefixed with `mut_`, like `.last` and `.mut_last`. – Havvy Aug 06 '14 at 04:36
3

A (much) more elegant solution for this particular case would be:

fn main() {
    let vec_2d = vec![vec![1i32]];

    println!("{:?}", vec_2d);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Kapichu
  • 3,346
  • 4
  • 19
  • 38