fn main() {
let a1 = &[1usize, 2, 3];
let a2 = &[1usize, 2, 3, 4, 5];
let v = [a1, a2];
println!("{v:?}");
}
The above Rust code fails to compile giving the following error message.
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:5:16
|
5 | let v = [a1, a2];
| ^^ expected an array with a fixed size of 3 elements, found one with 5 elements
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
However, if I manually specify a1 and a2 as slices, it compiles.
fn main() {
let a1: &[_] = &[1usize, 2, 3];
let a2: &[_] = &[1usize, 2, 3, 4, 5];
let v = [a1, a2];
println!("{v:?}");
}
Does this mean that &[1usize, 2, 3] is not a type of slice but can be implicitly casted to a slice when needed?
+-----+ // "Thin" pointer to an array
+ ptr | // Size: one `usize` big
+-----+ // Type: &[i32; 3] (different lengths implies different types)
|
V
+---+---+---+ // Size: statically known to be 12
| 1 | 2 | 3 | // Length: statically known be 3
+---+---+---+ // Type: [i32; 3] (different lengths implies different types)
&[1, 2, 3][..], &[1, 2, 3] as &[_]:
+-----+-----+ // "Wide" pointer to a slice (wide due to the length)
+ ptr | len | // Size: two `usize`s big
+-----+-----+ // Type: &[i32] (all lengths have the same type)
|
V
+---+---+---- // Size: statically unknown! (depends on the length)
| 1 | 2 | ... // Length: statically unknown! (stored in the wide pointer)
+---+---+---- // Type: [i32] (all lengths have the same type)
A reference to a slice (&[T]) is often just still called a slice. Because they're dynamically sized, a slice ([T]) is generally seen behind some sort of pointer (&[T], Box<[T]>, Arc<[T]>, ...). Arrays don't have that restriction.