Every chapter of The Rust Programming Language against this workspace · updated after lesson 0009
| Ch | Topic | State | Evidence / gap |
|---|---|---|---|
| 1–2 | Getting started, guessing game | Produced | hello_cargo/, guessing_game/ |
| 3 | Variables, types, functions, control flow | Produced | variables/, function/, control_flow/; 0001 diagnostic solid |
| 4 | Ownership, borrowing, slices | Produced | &self methods and &[Task] accessor in tasks/. Watch for: you have never hit
a borrow-checker fight in your own multi-owner code, because nothing has needed two owners yet. |
| 5 | Structs and methods | Produced | 0003 / 0004, tasks/src/task.rs |
| 6 | Enums and match | Produced | Status, Priority, Command, and now TaskError (0006) |
| 7 | Packages, crates, modules | Produced | tasks/ is a lib + bin package with four modules |
| 8 | Collections: Vec, String, HashMap | Produced | 0008 drill, in tasks/: HashMap<Priority, usize> built with the entry/or_insert
counting idiom, get().copied().unwrap_or(0), Eq + Hash + Copy derives on a key type, and a
String built by collect. Not done: BTreeMap, HashSet, string slicing by byte index. |
| 9 | Error handling: panic!, Result, ? | Produced | 0005 + 0006: ?, ok_or, own error enum, stderr + exit 1 |
| 10.1 | Generic data types | Produced | 0008 drill: fn tally<T, K, F>(items: &[T], key: F) -> HashMap<K, usize> in tasks/src/stats.rs,
with a where clause bounding K: Eq + Hash and F: Fn(&T) -> K — written from the
signature up, called at three different T/K pairs, one of them a non-Copy key.
Not done: generic structs and generic impl blocks. |
| 10.2 | Traits | Produced | Display for Task (0005), Display + Error + From for TaskError (0006),
FromStr for Task with an associated type Err and a hand-written PartialEq (0007) |
| 10.3 | Lifetimes | Gap — untouched | Zero exposure in this workspace. You have dodged it by owning everything (String, not &'a str).
Needed to read other people's code and to review a PR; not needed to ship your CLI. |
| 11 | Writing automated tests | Taught — drill pending | 0009: #[test], #[cfg(test)] mod tests with use super::*, the three assertion macros
and their failure output, #[should_panic(expected)] vs a -> Result<(), E> test, unit vs
integration access (E0603/E0616), tests/common/mod.rs, the runner flags, and why
src/main.rs is untestable — run moves to the library and writes to &mut impl Write.
Graded by six planted mutants, not by a test count. |
| 12 | I/O project: args, files, stderr, env | Produced | 0007: fs::read_to_string/fs::write, io::Error + ErrorKind::NotFound match guard,
env::var with a default, on top of env::args and stderr + exit 1 from 0005. Not done: BufReader,
file locking, serde — none needed at this size. |
| 13 | Closures and iterators | Produced | 0008 drill: filter/map/collect chains, find vs position,
Vec::retain, lines(), collect::<Result<Vec<_>, E>>() short-circuiting, and a
function that takes a closure (F: Fn). Not done: fold, zip,
impl Iterator for your own type. |
| 14 | Cargo, crates.io, workspaces | Skip for now | Learn cargo add and features when a dependency is actually needed (serde, axum). |
| 15 | Smart pointers: Box, Rc, RefCell, Deref, Drop | Partial | Box<dyn Error> met in 0005/0006. Rc/RefCell untouched — reach for them only when a real
shared-ownership problem appears, not before. |
| 16 | Concurrency: threads, channels, Send/Sync | Gap | Untouched apart from the Send + Sync bound your 0006 test asserts. Prerequisite for understanding
why an axum handler must be Send. |
| 17 | Async: futures, async/await, streams | Gap — by design | Required for axum/tokio, deliberately last. The unused trpl dependency in get-dependecies/ is
the abandoned first attempt. Do it after 8, 11, 13. |
| 18 | Trait objects, OOP patterns | Partial | dyn Error is the same mechanism as 18.2. The state-machine pattern (18.3) is optional reading. |
| 19 | Patterns and matching | Partial | match ✓, if let ✓ (0005 drill). Guards (Some(x) if x > 5), @ bindings,
let ... else, and matches! — one page of reading, high value per minute. |
| 20 | Unsafe, advanced traits, macros | Skip | Associated types and generic-parameter defaults matter eventually (serde uses them). Not now. |
| 21 | Final project: multithreaded web server | Not started | The natural capstone before axum — it is a backend service with no framework. |
After the 0009 drill, one gap in the book's core is left, and it is the mildest one:
titles_with returns Vec<&str> borrowed from &self, and
Status::label returns &str the same way. Elision filled both annotations in. Reading
other people's signatures needs the explicit form.@ bindings, matches!,
let … else. Your suite already uses matches!; the rest is high value per minute.Then serde → axum → async, where the traits from 0005–0008 and the testing from 0009 stop being an exercise and start being the whole API surface: an axum handler is a function a test can call. Chapter 21's web server is the natural capstone before a framework.