A Rust course built backwards on purpose
Read Rust. Then argue about it.
Almost every Rust course optimises for writing your first program. This one optimises for two different skills: reading Rust code with an accurate model of what it does, and discussing it credibly with people who write it for a living.
That change of goal changes the syllabus. The runtime model comes first. The borrow checker gets six lessons instead of one chapter, because three threshold concepts live in there. Traits are treated as a second programming language that runs before yours does. And the last part is vocabulary and argument, because a tech lead who cannot say“that trait isn’t dyn-compatible” out loud is not done learning.
- Lessons
- 28
- Honest hours
- 21
- Threshold concepts
- 5
- Done
- 0
Never read past a Predict box without typing an answer — a silent guess does not work, and the research on this is not subtle. Rate your confidence honestly; Calibrationwill show you where you are overconfident, which for an experienced engineer is the main thing standing between you and a correct model. Check predictions against a real compiler, not against your intuition. Come back to Review most days — it is deliberately mixed up rather than sorted by topic.
New here? Start with 0.1 — Why you will feel stupid, which explains why the course is built to be uncomfortable.
Orientation
How this course works, why it is deliberately uncomfortable, and the frame that holds everything else together.
- 0.1Why you will feel stupid, and why that is the planThis course is deliberately uncomfortable. Here is the evidence behind that choice, and the five rules that make it work.
- 0.2The three machinesRust does not have one execution model, it has three. Almost every moment of confusion is running the wrong one — plus a pretest you are meant to fail.
The runtime machine
What a Rust program actually does to memory. Places, moves, layout, fat pointers, and the exact moment a value dies.
- 1.1Values, places, and bindingsThe unlearning that everything else depends on. A Rust variable is not a label pointing at a value — it is a place that owns one.
- 1.2Stack, heap, and fat pointersSix ways to hold some bytes, and why three of them are two words wide. Once you see fat pointers you cannot unsee them.
- 1.3The four verbs: move, Copy, Clone, DropEverything that can happen to a value when it changes hands. Three of these are free; the one people fear is the one they reach for most.
- 1.4Where values dieDrop order, temporaries, and the two-line deadlock that catches every Rust programmer exactly once. This is the lesson that makes you sound experienced.
- 1.5Reading a stack frameAll of Part 1 applied to one real function, line by line — then a mixed set that refuses to tell you which idea it is testing.
The compile-time machine I — borrows & lifetimes
Three threshold concepts live here, so this part is deliberately oversized. Expect to feel stuck. That is the mechanism.
- 2.1Aliasing XOR mutabilityRust has one rule about references. Everything the borrow checker ever says to you is a consequence of it — including the parts that feel unfair.
- 2.2`&mut` does not mean mutableThe keyword is misnamed, and the misnaming costs people months. Read it as "exclusive" and a whole category of confusion disappears.
- 2.3Lifetimes are regions of code, not durations of timeThe single most damaging misconception in Rust. A lifetime is not how long a value lives — it is a set of places in your program, and it is inferred, not chosen.
- 2.4Reading lifetime annotationsThe practical half. Elision rules, the anonymous lifetime, the two meanings of `static`, and enough variance to follow the conversation.
- 2.5The borrow checker's errors are the curriculumNine error codes cover almost everything the borrow checker will ever say to you. Each one reveals a specific piece of the model.
- 2.6The escape hatchesOwnership is a tree. Your data might be a graph. Interior mutability does not break the rule — it moves the check from compile time to run time, and you pay for it.
The compile-time machine II — types & traits
The trait system is a second programming language that runs before yours does. This is where reading Rust is won.
- 3.1Enums are TypeScript discriminated unions, done rightYour strongest advantage in this entire course. You already think in sum types — Rust just enforces what TypeScript asks you to remember.
- 3.2Traits are constraints, not typesA trait is not an interface and not a type. It is a predicate about types, and the difference explains coherence, the orphan rule, and why `impl` blocks are separate from `struct` definitions.
- 3.3Dispatch and monomorphisationWhere constraints become machine code. This lesson explains Rust build times, binary sizes, and `dyn` — which are all the same fact.
- 3.4Where does this method come from?Auto-ref, auto-deref, and coercion happen silently on every method call. This is the single most useful reading skill in Rust, and almost nobody teaches it.
- 3.5`Result`, `?`, and the error ecosystemErrors are values, panics are bugs, and the difference is a design decision you will be asked to defend. Plus the `thiserror` vs `anyhow` question, answered.
- 3.6Reading generic signatures in the wildThe capstone. A repeatable five-step procedure, applied to real signatures from serde, tokio and axum — the ones that look like noise until they suddenly do not.
Concurrency & async
Send, Sync, and the biggest trap a JavaScript developer walks into: futures do nothing until something polls them.
- 4.1`Send` and `Sync`Two traits with no methods, derived automatically, that give Rust thread safety without a single new rule. Also: exactly what "fearless concurrency" does and does not promise.
- 4.2Threads, channels, and shared stateWhat the concurrency primitives actually look like, how they compare to goroutines and `synchronized`, and why scoped threads changed the ergonomics.
- 4.3Futures are inertThe single biggest trap for a JavaScript developer. Calling an async function in Rust does not start anything — and two `.await`s in a row are not concurrent.
- 4.4The async ecosystem and its argumentsThe live disagreements: runtime lock-in, function colouring, work-stealing versus thread-per-core, and whether you needed async at all.
Unsafe & real code
What unsafe actually turns off (much less than you think), the idiom catalogue, and a guided read of a real crate.
- 5.1`unsafe` does not turn off the borrow checkerIt unlocks exactly five abilities and disables nothing. The widespread belief that it is an escape hatch from the borrow checker is the fastest way to sound like you have only read about Rust.
- 5.2The idiom catalogueFourteen patterns that make up most of the Rust you will ever read. Each one is a beacon: see it, know it, stop decoding it.
- 5.3Reading a real crateA repeatable procedure for understanding code you have never seen, built on the one model of program comprehension that actually tells you what to look at.
Speaking Rust
The vocabulary, the live arguments, and scripts for the conversations a tech lead actually has about Rust.
- 6.1The lexicon and the discourseKnowing what dyn-compatible means and being able to say “that trait isn’t dyn-compatible” in a review are different skills. This is the second one.
- 6.2Explaining Rust to your teamThe last lesson. Scripts for the seven conversations a tech lead actually has about Rust — including the one where the honest answer is no.