0

I'm very new to rust, and am starting to get the hang of the ownership system and such, but am still having some hangups. For exmaple, I have the following code:

fn main() {
    let mut t = vec![Box::new(4)];
    let mut o = t[0];
    *o = *o + 1;
    t[0] = o;
    println!("t[0]:{}", t[0]);
}

Which gives me the cannot move out of indexed content error for the line where I'm initializing o. I understand why this is happening, I think, but I can't figure out what I'm supposed to do instead to accomplish the same thing. This is a very simplified case, but any help would be greatly appreciated. Thanks!

Mediocre Gopher
  • 2,274
  • 1
  • 22
  • 39
  • I'd encourage you to link to the other questions here on stack overflow that have the same error message and explain how your question differs from them. – Shepmaster Jun 12 '16 at 20:51
  • 1
    I'd appreciate it if you unmarked this as duplicate. The answer in that other thread doesn't seem to apply here, I've tried adding the `&` operator and that merely opens up a new can of errors. Moreover the other thread doesn't deal with re-setting the value in the vector, which I'm trying to do. You can see below the answers are very different. – Mediocre Gopher Jun 12 '16 at 22:03
  • Absolutely. [edit] your question to include a link to the other question and describe why it's not a duplicate. This will help future searchers understand why both questions need to exist. – Shepmaster Jun 12 '16 at 22:05

1 Answers1

5

The expression t[0] is equivalent to either *t.index(0) or *t.index_mut(0), based on context. These methods return an immutable reference and a mutable reference, respectively. The indexing operator automatically dereferences these.

Since you have a vector of Box<i32>, dereferencing is not valid, because that would try to move the value from the vector. But then, what do you put in the vector in its place?

Instead of trying to move the value, you need to use a reference to the value instead. Also, if you want to be able to add 1 to the value, you need a reference to the value, not a reference to the Box. You can do this by first dereferencing the box, then by taking a mutable reference to the result:

fn main() {
    let mut t = vec![Box::new(4)];
    {
        let o = &mut *t[0];
        *o = *o + 1;
    }
    println!("t[0]:{}", &t[0]);
}

I had to add a block here to make the mutable borrow end before the println!, otherwise the compiler complained with:

error: cannot borrow `t` as immutable because it is also borrowed as mutable

Also, notice how we don't need to put the updated value back in the vector, because we changed the value in the vector directly by using a reference to it.

Francis Gagné
  • 60,274
  • 7
  • 180
  • 155