Reading the basic introduction:
If you try to use a subscript that is not in the array, you will get an error: array access is bounds-checked at run-time.
Why does Rust check array bounds at runtime, when it seems most other checks occur at compile time?
Because checking indices at compile time is not feasible in the general case. Reasoning about the possible values of arbitrary variables is somewhere between hard and impossible even for small programs. Nobody wants to have to:
- formally prove that the index can't be out of bounds, and
- encode that proof into the type system
... for every single slice/Vec
/etc. access, because that's what you'd have to do to perform bounds checks at compile time. You essentially need dependent typing.
Aside from possibly making type checking undecidable (and getting a program to type check vastly harder), type inference becomes impossible in general (and far more restricted in the best case), types get much more complicated and wordy, and the complexity of the language increases significantly. That indices are in bounds can only be proven without significant additional programmer effort in very simple circumstances.
Furthermore, there is little incentive to get rid of bounds checks. Lifetimes pull their weight by almost entirely eliminating the need for garbage collection --- which is a huge, invasive feature with unpredictable throughput, space and latency implications. Run-time bounds checking in the other hand is very non-invasive, has a small and well-known overhead, and can be selectively turned off in performance-critical sections even if the entire rest of the program uses it liberally.
Note that the compiler can do some simple checks for out-of-bounds access of arrays:
let a = [1, 2];
let element = a[100];
error: index out of bounds: the len is 2 but the index is 100
--> src/main.rs:3:19
|
3 | let element = a[100];
| ^^^^^^
|
= note: #[deny(const_err)] on by default
However, this is limited and is easily avoided by making the index value not an "obvious" constant:
let a = [1, 2];
let idx = 100;
let element = a[idx];