5

Why this doesn't compile:

fn main() {
    let mut b = Box::new(Vec::new());
    b.push(Vec::new());
    b.get_mut(0).unwrap().push(1);
}

While this does:

fn main() {
    let a = Box::new(Vec::new());
    let mut b = *a;
    b.push(Vec::new());
    b.get_mut(0).unwrap().push(1);
}

And also this does:

fn main() {
    let mut b = Vec::new();
    b.push(Vec::new());
    b.get_mut(0).unwrap().push(Vec::new());
    b.get_mut(0).unwrap().get_mut(0).unwrap().push(1)
}

The first and third one for me are the conceptually the same - Box of a Vector of Vectors of integers and a Vector of Vector of Vectors of integers, but the last one results in each vector being mutable, whereas the first one makes the inner vector immutable.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
PL_kolek
  • 325
  • 3
  • 9

2 Answers2

3

In at least Rust 1.25.0, all three original examples work. This was a bug in some previous version of Rust.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
0

You need to unbox your value before accessing it as a mutable:

fn main() {
    let mut b = Box::new(Vec::new());
    b.push(Vec::new());
    (*b).get_mut(0).unwrap().push(1);
}

This is because the . operator uses the Deref trait instead of DerefMut.

The best way to achieve this would be:

fn main() {
    let mut b = Box::new(Vec::new());
    b.push(Vec::new());
    b[0].push(1);
}
Hauleth
  • 22,873
  • 4
  • 61
  • 112
  • 1
    Sorry for my English, but I've overdosed caffeine and it is hard to concentrate. – Hauleth Feb 07 '15 at 19:35
  • If the `.` operator only uses `Deref`, then why would `b.push(Vec::new())` work? That requires a mutable receiver, no? – Shepmaster Feb 07 '15 at 19:41
  • I have no idea and it is too late for me to think. But `get_mut` will propably get deprecated in favour of `IndexMut`. Instead you can use `b[0].push(1)` and it will work fine. I could investigate it for you tomorrow. – Hauleth Feb 07 '15 at 19:51
  • 2
    This looks like a bug. It's like the compiler is failing to infer that it needs to use `deref_mut` *twice* to reach `get_mut`. The error is the same if you try to do `b.deref().deref_mut()`. – DK. Feb 08 '15 at 03:14