Index for array

It seems array does not implement the Index trait, if so , how can we index it? It is treated specially by compiler ?

Arrays coerce to slices, and the slice type [T] implements the Index trait.

so when the coerce happened ? at A or B? It seems the type of a is [i32;3].

let a = [1,2,3];    // A
a[1];               // B

It happens at B.

Coercion also happens at method calls, so you can call slice methods like a.get(1).

The indexing syntax a[1] is shorthand for a method call, *a.index(1).

I'm curious about the detail. So I dived into the compiler code, if at this line , the type of base is a slice it will explain it, but I can not figure out how type of base is corece to a slice.

Actually, arrays are kinda special and index access is done directly by the compiler and no coercion happens. If you access the array out-of-bounds, you'll get an unconditional panic compile-time error, which can be turned off and the resulting code will simply have a test call directly, instead of calling Index::index.

#![allow(unconditional_panic)]
fn main() {
    let a = [1, 2, 3];
    dbg!(a[3]);
}

will turn into

playground::main:
	pushq	%rbx
	subq	$304, %rsp
	xorl	%eax, %eax
	movl	$1, 104(%rsp)
	movl	$2, 108(%rsp)
	movl	$3, 112(%rsp)
	testb	$1, %al
	jne	.LBB18_1
	jmp	.LBB18_8

.LBB18_1:
	movl	116(%rsp), %eax
	movl	%eax, 116(%rsp)
	movq	.L__unnamed_2(%rip), %rcx
	movq	.L__unnamed_3(%rip), %rdx
	movq	.L__unnamed_4(%rip), %rsi
	movq	.L__unnamed_5(%rip), %rdi
	leaq	116(%rsp), %r8
	movq	%r8, 264(%rsp)
	movq	%rdx, 232(%rsp)
	movq	%rsi, 240(%rsp)
	movq	%rdi, 248(%rsp)
	leaq	264(%rsp), %rdx
	movq	%rdx, 256(%rsp)
	movq	232(%rsp), %rdx
	movq	%rdx, 272(%rsp)
	movq	240(%rsp), %rsi
	movq	%rsi, 280(%rsp)
	movq	248(%rsp), %rdi
	movq	%rdi, 288(%rsp)
	movq	256(%rsp), %r8
	movq	%r8, 296(%rsp)
	movq	%rdi, 96(%rsp)
	movq	%rdx, %rdi
	leaq	<&T as core::fmt::Display>::fmt(%rip), %rdx
	movq	%rsi, 88(%rsp)
	movq	%rdx, %rsi
	movq	%rcx, 80(%rsp)
	movq	%r8, 72(%rsp)
	callq	core::fmt::ArgumentV1::new
	movq	%rax, 64(%rsp)
	movq	%rdx, 56(%rsp)
	movq	core::fmt::num::imp::<impl core::fmt::Display for u32>::fmt@GOTPCREL(%rip), %rsi
	movq	88(%rsp), %rdi
	callq	core::fmt::ArgumentV1::new
	movq	%rax, 48(%rsp)
	movq	%rdx, 40(%rsp)
	movq	96(%rsp), %rdi
	leaq	<&T as core::fmt::Display>::fmt(%rip), %rsi
	callq	core::fmt::ArgumentV1::new
	movq	%rax, 32(%rsp)
	movq	%rdx, 24(%rsp)
	movq	72(%rsp), %rdi
	leaq	<&T as core::fmt::Debug>::fmt(%rip), %rsi
	callq	core::fmt::ArgumentV1::new
	movq	%rax, 16(%rsp)
	movq	%rdx, 8(%rsp)
	movq	64(%rsp), %rax
	movq	%rax, 168(%rsp)
	movq	56(%rsp), %rcx
	movq	%rcx, 176(%rsp)
	movq	48(%rsp), %rdx
	movq	%rdx, 184(%rsp)
	movq	40(%rsp), %rsi
	movq	%rsi, 192(%rsp)
	movq	32(%rsp), %rdi
	movq	%rdi, 200(%rsp)
	movq	24(%rsp), %r8
	movq	%r8, 208(%rsp)
	movq	16(%rsp), %r9
	movq	%r9, 216(%rsp)
	movq	8(%rsp), %r10
	movq	%r10, 224(%rsp)
	leaq	168(%rsp), %r11
	movq	.L__unnamed_6(%rip), %rbx
	leaq	120(%rsp), %rdi
	movq	80(%rsp), %rsi
	movl	$5, %edx
	movq	%r11, %rcx
	movl	$4, %r8d
	movq	%rbx, %r9
	movq	$4, (%rsp)
	callq	core::fmt::Arguments::new_v1_formatted
	leaq	120(%rsp), %rdi
	callq	*std::io::stdio::_eprint@GOTPCREL(%rip)
	addq	$304, %rsp
	popq	%rbx
	retq

.LBB18_8:
	leaq	.L__unnamed_7(%rip), %rdx
	movq	core::panicking::panic_bounds_check@GOTPCREL(%rip), %rax
	movl	$3, %ecx
	movq	%rcx, %rdi
	movq	%rcx, %rsi
	callq	*%rax
	ud2
1 Like

I think I found it at this line, among other things, this will let the a[1] pass type check.