I read What are Rust's exact auto-dereferencing rules? from beginning to end, but I still have a question about the coercion from array to slice.
Let us think ab
This kind of coercion is intended to work, but not implemented.
Arrays do not implement Deref, so the coercion &[T; n] -> &[T] is not a deref coercion and does not work in quite the same way as one. Instead, it's called an "unsized coercion" because it turns a sized type ([T; n]) into an unsized one ([T]).
That said, the language reference (which is not normative and may be outdated, but bear with me) lists the possible coercions, including the following (emphasis added):
T_1toT_3whereT_1coerces toT_2andT_2coerces toT_3(transitive case)Note that this is not fully supported yet
&Tto&UifTimplementsDeref<Target = U>.TyCtor(
T) to TyCtor(U), where TyCtor(T) is one of
&T&mut T*const T*mut TBox<T>and where
Tcan be obtained fromUby unsized coercion.
The last bullet, unsized coercion, is what allows &[T; n] to coerce to &[T]. Notably, this only describes one layer of referencing; it doesn't cover the &&[T; n] -> &[T] case (for which we also need Deref coercion).
Back to your non-working example:
let arr: &[i32] = &&&[1, 2, 3, 4, 5];
The intended coercion is &&&[i32; 5] -> &[i32]. We can work out how this coercion ought to work:
&[i32; 5] coerces to &[i32] by unsizing;&&[i32; 5] coerces to &[i32; 5] by Deref;&&[i32; 5] coerces to &[i32] by transitivity.&&&[i32; 5] coerces to &&[i32; 5] by Deref;&&&[i32; 5] coerces to &[i32] by transitivity.But it doesn't. The quote above hints at why: under the transitive case, it says "Note that this is not fully supported yet". As far as I can tell, according to issue #18602, "not fully supported" is a hedge; it would be more accurate to say "unimplemented". So, for now, coercion via transitivity is not possible at all. Apparently this issue is not a high priority, probably because sized arrays aren't very common. (I suspect this might become a more common complaint when const generics land, since that may make arrays more useful.)
So why does arr.first() work? Well, the "auto-dereferencing rules" used to find methods invoked with the . (dot) operator are an extension of the coercion rules. Autoderef is similar to manually dereferencing any number of times until you get something (that can be coerced to a type) with the given method. This means you don't need transitivity to find method calls through autoderef (which RFC 401 calls "receiver coercion").
RFC #401 describes intended semantics of most coercions. This RFC was merged over 5 years ago. Many things have changed since then, but it is still not fully implemented (its tracking issue is #18469), so RFC 401 does not accurately describe any past, present, or future version of Rust. Nevertheless, RFC 401 also would permit coercion of &&&[i32; 5] to &[i32] and by almost the same logic.
The Rustonomicon also has a chapter on coercions and appears to agree with the reference book.