Why are both &[u8]
and &[u8; 3]
ok in this example?
fn main() { let x: &[u8] = &[1u8, 2, 3]; println!("{:?}", x); let y: &[u8; 3] = &[1u8, 2, 3]; println!("{:?}", y); }
The fact that
&[T; n]
can coerce to&[T]
is the aspect that makes them tolerable. — Chris Morgan
Why can &[T; n]
coerce to &[T]
? In what other conditions does this coercion happen?
JavaScript Array slice()The slice() method returns selected elements in an array, as a new array. The slice() method selects from a given start, up to a (not inclusive) given end. The slice() method does not change the original array.
In Go language slice is more powerful, flexible, convenient than an array, and is a lightweight data structure. Slice is a variable-length sequence which stores elements of a similar type, you are not allowed to store different type of elements in the same slice.
In computer programming, array slicing is an operation that extracts a subset of elements from an array and packages them as another array, possibly in a different dimension from the original.
slice is a composite data type and because it is composed of primitive data type (see variables lesson for primitive data types). Syntax to define a slice is pretty similar to that of an array but without specifying the elements count. Hence s is a slice.
[T; n]
is an array of length n
, represented as n
adjacent T
instances.
&[T; n]
is purely a reference to that array, represented as a thin pointer to the data.
[T]
is a slice, an unsized type; it can only be used through some form of indirection.
&[T]
, called a slice, is a sized type. It's a fat pointer, represented as a pointer to the first item and the length of the slice.
Arrays thus have their length known at compile time while slice lengths are a runtime matter. Arrays are second class citizens at present in Rust, as it is not possible to form array generics. There are manual implementations of the various traits for [T; 0]
, [T; 1]
, &c., typically up to 32; because of this limitation, slices are much more generally useful. The fact that &[T; n]
can coerce to &[T]
is the aspect that makes them tolerable.
There is an implementation of fmt::Debug
for [T; 3]
where T
implements Debug
, and another for &T
where T
implements fmt::Debug
, and so as u8
implements Debug
, &[u8; 3]
also does.
Why can
&[T; n]
coerce to&[T]
? In Rust, when does coercion happen?
It will coerce when it needs to and at no other times. I can think of two cases:
&[T]
and you give it a &[T; n]
it will coerce silently;x.starts_with(…)
on a [T; n]
it will observe that there is no such method on [T; n]
, and so autoref comes into play and it tries &[T; n]
, which doesn’t help, and then coercion come into play and it tries &[T]
, which has a method called starts_with
.The snippet [1, 2, 3].starts_with(&[1, 2])
demonstrates both.
Why can
&[T; n]
coerce to&[T]
?
The other answer explains why &[T; n]
should coerce to &[T]
, here I'll explain how the compiler works out that &[T; n]
can coerce to &[T]
.
There are four possible coercions in Rust:
Transitivity.
T
coerces to U
and U
coerces to V
, then T
coerces to V
.Pointer weakening:
&mut T
→ &T
and *mut T
→ *const T
&mut T
→ *mut T
and &T
→ *const T
Deref
trait:
T: Deref<Target = U>
, then &T
coerces to &U
via the deref()
methodT: DerefMut
, then &mut T
coerces to &mut U
via deref_mut()
)Unsize
trait:
If Ptr
is a "pointer type" (e.g. &T
, *mut T
, Box
, Rc
etc), and T: Unsize<U>
, then Ptr<T>
coerces to Ptr<U>
.
The Unsize
trait is automatically implemented for:
[T; n]: Unsize<[T]>
T: Unsize<Trait>
where T: Trait
struct Foo<…> { …, field: T }: Unsize< struct Foo<…> { …, field: U }>
, provided that T: Unsize<U>
(and some more conditions to make the job easier for the compiler)(Rust recognizes Ptr<X>
as a "pointer type" if it implements CoerceUnsized
. The actual rule is stated as, “if T: CoerceUnsized<U>
then T
coerces to U
”.)
The reason &[T; n]
coerces to &[T]
is rule 4: (a) the compiler generates the implementation impl Unsize<[T]> for [T; n]
for every [T; n]
, and (b) the reference &X
is a pointer type. Using these, &[T; n]
can coerce to &[T]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With