Reputation: 63
I'm reading The Rust book and I run across this example:
fn main() {
let a = [1, 2, 3, 4, 5];
let index = 10;
let element = a[index];
println!("The value of element is: {}", element);
}
And in the book it says that after running cargo run
...
The compilation didn’t produce any errors, but the program resulted in a runtime error and didn’t exit successfully.
I don't understand this. I see a compilation error, and even when I compile via cargo build
or rustc src/main.rs
I also see the error.
What do they mean in this example? Why is that not a compilation error, but rather a runtime one?
Upvotes: 5
Views: 2593
Reputation: 3057
Compiler is smarter now than it was so it produces compile error.
You need to change code to be less easy to validate for compiler. For example:
fn main() {
let a = [1, 2, 3, 4, 5];
let index = a.len() + 1;
let element = a[index];
println!("The value of element is: {}", element);
}
Code above compiles and panics at current version (1.60).
Also, generally compiler can prove bounds access only for arrays ([T; N]
) but not slices and Vec
s.
Upvotes: 2
Reputation: 13518
Rust got smarter constant evaluation since the book was written. There is an open pull request that updates the chapter to the following:
What happens if you try to access an element of an array that is past the end of the array? If you change the example to the following code, it will not compile:
fn main() {
let a = [1, 2, 3, 4, 5];
let index = 10;
let element = a[index];
println!("The value of element is: {}", element);
}
Building this code using
cargo build
produces the following result:
$ cargo run
Compiling arrays v0.1.0 (file:///projects/arrays)
error: this operation will panic at runtime
--> src/main.rs:5:19
|
5 | let element = a[index];
| ^^^^^^^^ index out of bounds: the len is 5 but the index is 10
|
= note: `#[deny(unconditional_panic)]` on by default
error: aborting due to previous error
error: could not compile `arrays`.
To learn more, run the command again with --verbose.
When the compiler can prove that invalid array access occurs, it will fail to compile. However, there are some cases where the compilation won't produce any errors, but the program itself will fail with a runtime error and won't exit successfully.
At runtime, when you attempt to access an element using indexing, Rust will check that the index you’ve specified is less than the array length. If the index is greater than or equal to the array length, Rust will panic.
This is the first example of Rust’s safety principles in action. In many low-level languages, this kind of check is not done, and when you provide an incorrect index, invalid memory can be accessed. Rust protects you against this kind of error by not allowing the program to compile, or it might panic at runtime if the error could not be identified at compile-time, which would immediately exit the program instead of allowing the invalid memory access to occur. Chapter 9 discusses more of Rust’s error handling.
Upvotes: 1