Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Rust's compiler errors are famously good — but only if you've learned to read them. They follow a structured format: an error code (E0382, E0277), a primary span pointing at the bug, secondary spans showing related context, and often a suggested fix you can apply with cargo fix. The borrow checker errors look intimidating the first time but become routine after 20 of them. Spending an hour deliberately reading 5 borrow-checker errors will save you a month of confusion.
The borrow checker enforces Rust's ownership rules at compile time: every value has exactly one owner, and at any point in the program you can have either one mutable reference or any number of immutable references — never both simultaneously. When you violate these rules, the compiler emits a structured error with the conflicting borrow spans highlighted. Reading these errors fluently is the core learning curve of Rust; once you can mentally model why each error fires, you stop fighting the borrow checker and start using it as a design tool.
rustc --explain E0382. This works for every error code; it gives you the canonical explanation.#[derive(Debug)]. The error tells you exactly what to add.cargo fix --bin myapp — for many errors the compiler will apply the suggested fix automatically.Use these three in order. Each builds on the one before.
In one paragraph, explain why Rust's compiler errors point at multiple lines (with `^` carets) instead of just one — what extra context are they giving me?
Walk me through how the borrow checker actually flags use-after-move: at what compilation phase does this happen, what's the data flow analysis?
When I get a confusing trait-bound error (a wall of red text), what's a systematic way to narrow it down? Cover `cargo expand`, `--diagnostic-width`, `RUSTFLAGS='-Zmacro-backtrace'`, and rust-analyzer's hover.
// classic 'use after move':
fn main() {
let s = String::from("hello");
let t = s; // moves s into t
println!("{}", s); // ERROR
}
/*
error[E0382]: borrow of moved value: `s`
--> src/main.rs:4:20
|
2 | let s = String::from("hello");
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
3 | let t = s;
| - value moved here
4 | println!("{}", s);
| ^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let t = s.clone();
| ++++++++
For more information about this error, try `rustc --explain E0382`.
*/
// run `rustc --explain E0382` for a full essay on this error class.cargo run