Why does primitive 'array' type not implement traits 'Index', 'IndexMut'?

Hello dear Rustaceans :crab: ,

I'm a bit puzzled with the fact that the primitive array type does not implement the traits Index<I> & IndexMut<I>.
The primitive array type implements 19 different traits, but they all seem irrelevant to indexing behavior.

In contrast, vector type Vec<T> implements both the traits Index<I> and IndexMut<I>.

Where should I look to find out the implementation of indexing of primitive array types ??

As I understand it, indexing a [T; N] first uses the impl Deref<Target=[T]> for [T; N] to get an &[T], and then the Index implementation of [T]. In general, all operations (method calls, field access, and things like indexing) will try to use Deref any number of times if the operation isn't available on the type itself.

See the rust book chapter on Deref and the implementation of Index for [T].

1 Like

Not entirely. Fun fact: arrays don't impl Deref!

...but I do think they are somehow hardcoded in the compiler to coerce to slices in a manner which supports method resolution and operator traits, as if they impl'd Deref. This makes it possible it to work on arrays of ALL lengths rather than only those up to length 32.


Or more likely, the aforementioned hardcoded hack is only for method resolution (e.g. [0; 64].len()), and then indexing is simply implemented as a built-in operation of the array type, rather than being resolved through the Index trait. (much like how writing *p on a &T, &mut T, or Box<T> doesn't actually desugar to a Deref call)

6 Likes

Could arrays use Deref proper once const generics seems stable? Or even right now, since the compiler can use unstable features internally?

I honestly don't see any reason why arrays couldn't just impl Index<I> where I: SliceIndex<[T]> for sizes up to 32 like they do for other traits. Maybe there's some super crazy technical reason that goes beyond the knowledge of us mere mortals?

I wouldn't know. In any case, the only time it matters is when you try to use an array type as T in some generic function with a T: Index bound. (personally, I'm not sure if I have ever used Index as a bound! I guess maybe if you were writing some kind of generic-array abstraction that supported both dynamic-sized Vecs and fixed-size arrays?)

Arrays not implementing Deref is probably a deliberate decision though, because they're not a pointer-like type.

1 Like

Wouldn't it be better then to just have arrays impl Deref? The current implementation sounds like a hand-hacked version of Deref that accomplishes the same thing. Seems awfully redundant to me.

I think the point is so that the * operator doesn't work on arrays.

Also, prior to const generics, if they did this through Deref, it would only be able to work for sizes up to 32.

1 Like