rustvectorindexingslicemove-semantics

Why does index [] try to move value, but calling index directly does not


Example:

use std::ops::Index;

fn test(v: &Vec<Vec<i32>>) {  
    let t = v.index(0); //ok
    let t = v[0]; //error, Vec<i32> does not implement Copy trait
}

Playground

Why does that happen? As specified in the documentation:

fn index(&self, index: I) -> &<Vec<T, A> as Index<I>>::Output

Performs the indexing (container[index]) operation

So it should be the same.


Solution

  • There is a hidden dereference when you use square brackets. The Index trait documentation says:

    container[index] is actually syntactic sugar for *container.index(index)

    If you add * to the first line then you get the same error message:

    error[E0507]: cannot move out of a shared reference
     --> src/lib.rs:4:13
      |
    4 |     let t = *v.index(0);
      |             ^^^^^^^^^^^ move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
      |
    help: consider removing the dereference here
      |
    4 -     let t = *v.index(0);
    4 +     let t = v.index(0);
      |
    

    Playground