doki
doki

Reputation: 115

Why the result of Index::index is dereferenced?

I have some code like this

struct MyStruct {
    id: u32
}

fn main() {
    let vec: Vec<MyStruct> = vec![MyStruct {
        id: 1
    }];
    let my_struct = vec[0];
}

I thought my_struct must be of reference type, but the compiler proved I was wrong:

error[E0507]: cannot move out of index of `Vec<MyStruct>`
  --> src/main.rs:10:21
   |
10 |     let my_struct = vec[0];
   |                     ^^^^^^ move occurs because value has type `MyStruct`, which does not implement the `Copy` trait
   |
help: consider borrowing here
   |
10 |     let my_struct = &vec[0];
 

So I read the doc of trait Index and noticed the sentence below:

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

It's counterintuitive. Why rust dereferences it? Does it mean that it's more friendly to types those impl Copy?

Upvotes: 2

Views: 105

Answers (1)

kmdreko
kmdreko

Reputation: 60187

There are plenty of other questions asking about this (1 2 3) but none really address the why part.

Rust has made many design decisions work to make ownership clear. For example, you cannot pass a value, v, directly to a function f that expects a reference. It must be f(&v). There are places where this isn't always the case (macros like println! and auto-ref for method calls being prime exceptions), but many parts of the language follow this principle.

The behavior of the index operator is pretty much the same as the normal field access operator .. If you have my_struct: &MyStruct then my_struct.id will yield a u32 and not a &u32. The default behavior is to move fields. You have to introduce a & (i.e. &my_struct.id) to get a reference to the field. So the same is with the index operator. If you want to make it clear that you want only a reference to the element, then you need to introduce a &.

Upvotes: 2

Related Questions