Day-0 → Month-3 · ownership · zero-cost
Languages / Rust

Rust

Ownership and borrowing as the language's foundation. Memory safety without a garbage collector. The borrow checker is alien for a week and then — once it clicks — becomes a thought tool. Modern systems programming: Cloudflare's Pingora, Firefox internals, parts of the Linux kernel, the next generation of databases and embedded.


Why Rust.

Rust is what you reach for when you want C-level performance, no garbage collector, and memory safety guaranteed at compile time. Started at Mozilla in 2006 by Graydon Hoare to fix the constant stream of memory-corruption CVEs in Firefox; today it powers Cloudflare's network edge (Pingora), Microsoft's security-critical Windows components, parts of Linux, and an entire new generation of databases (SurrealDB, ScyllaDB internals, redb, sled).

The trade: the first month is hard. The borrow checker rejects programs that work in Go or Python. The compiler errors are long. There are three ways to take a reference (&, &mut, Box) and you need them all. The reward: once Rust accepts your program, whole classes of bugs are gone — no use-after-free, no data races, no null-pointer dereferences. You ship correct software faster.

The 12 mental models.

Twelve ideas that, once internalised, make the rest of the language read naturally. Skim once now; come back after a week of writing Rust.

  1. Day-zero

    Ownership

    Every value has exactly one owner. When the owner goes out of scope, the value is dropped. No GC, no manual free — the compiler tracks lifetimes.

  2. Day-zero

    Borrowing

    &T = many shared readers; &mut T = exactly one exclusive writer. Never both at once. The aliasing-XOR-mutation rule eliminates a class of bugs.

  3. Day-zero

    Lifetimes

    References have lifetimes. Mostly inferred; sometimes annotated as 'a. They're how the compiler proves references stay valid.

  4. Day-zero

    Move semantics

    Assignment moves by default. After let b = a, using a is a compile error. Clone for explicit copies; Copy trait for cheap types.

  5. Day-zero

    Trait

    Like an interface but with explicit impl Trait for Type. Coherence rules prevent ambiguity. Generics are constrained by traits.

  6. Day-zero

    Result<T, E>

    No exceptions. Fallible functions return Result. The ? operator propagates errors in one character.

  7. Day-zero

    Option<T>

    No nulls. A value either is Some(x) or None. Pattern matching forces you to handle both.

  8. Practitioner

    Pattern matching

    match is exhaustive — compile error if you miss a case. if let, while let for ergonomic single-case match.

  9. Practitioner

    Smart pointers

    Box<T> for heap, Rc<T> for shared ownership single-thread, Arc<T> shared multi-thread, RefCell<T> for interior mutability.

  10. Practitioner

    Iterators

    Lazy. .map, .filter, .collect compose without allocating intermediates. Compiles down to tight loops.

  11. Runtime

    Async / Future

    A Future is a state machine. async/await is sugar over it. Need an executor (tokio, async-std) to actually run.

  12. Runtime

    unsafe

    An escape hatch — raw pointers, FFI, manual lifetimes. The compiler trusts you inside. Use sparingly; document why.

Day-zero — the first hour.

Sixty minutes from "never wrote Rust" to "wrote your first Rust program". This is the prerequisite for the week.

  1. Install rustup. One line: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh. Installs rustc, cargo, the toolchain manager.
  2. Verify. cargo --version and rustc --version in a fresh terminal.
  3. Editor. VS Code + rust-analyzer is the no-friction default. RustRover (JetBrains) is the paid option.
  4. Or skip install entirely. play.rust-lang.org runs every example on these pages.
  5. Run hello. cargo new hello && cd hello && cargo run. Done.

Day-1 to Day-7.

The week. Each day has a topic and a hands-on task. Aim for one focused 90-minute session per day; revisit nights as needed.

DayTopicTask
1 Hello, Rust Install rustup. Run cargo new hello. Read main.rs. Modify Cargo.toml. Compile and run.
2 Ownership and borrowing The famous day. Internalise move, &T, &mut T. Stop fighting the borrow checker.
3 Structs, enums, pattern matching Build a small CLI that parses commands as enum variants. Use match exhaustively.
4 Traits and generics Write a Sortable trait. Implement for two types. Pass &dyn Sortable to a function.
5 Error handling Replace .unwrap() with ?. Define a custom error enum. Use thiserror to skip boilerplate.
6 Concurrency, async Spawn a tokio task. Send between tasks with mpsc. Run two tasks with select!.
7 Cargo, tests, idioms cargo test, cargo clippy, cargo doc. Read three crates on crates.io. Internalise the formatter.

The full concept walkthrough expands each day to 2–3 deep dives.

Week-1 to Month-3.

Once the week is done, these seven tracks are where you spend the next 90 days. Pick whatever your day-job touches first.

  1. Track

    Async ecosystem

    tokio for I/O. async-std as an alternative. Pin, Future, Waker — the runtime mechanics underneath async/await.

  2. Track

    Standard library

    std::collections (Vec, HashMap, BTreeMap, VecDeque). std::io (Read, Write, BufRead). std::sync (Mutex, Arc, Barrier, mpsc).

  3. Track

    Performance

    cargo bench, criterion, perf, flamegraph. Profile-guided optimisation. Inline hints. Avoiding allocations.

  4. Track

    Web services

    axum (tokio-based), actix-web (own runtime), rocket. The serde + tokio + axum stack is the modern default.

  5. Track

    Embedded / no_std

    Rust without the heap. The Embedded Rust Book. RTIC, embassy. Targets ARM Cortex, RISC-V, AVR.

  6. Track

    Macros

    macro_rules! for declarative. Procedural macros for derive (#[derive(Debug)]), attribute, function-like. Heavy stuff.

  7. Track

    unsafe and FFI

    Raw pointers, manual lifetimes, calling C, building libraries that C calls. The bindgen and cbindgen tools.

The borrow checker in one paragraph.

At every point in your program, a value has exactly one owner — usually a variable binding. References to that value are either many shared (&T, read-only) or exactly one exclusive (&mut T, read-write) — never both at once. References must not outlive the value they point at; the compiler tracks the lifetimes either by inference or via explicit 'a annotations. When the owner goes out of scope, the value is dropped — destructors run automatically. This is enough to prove, at compile time, that the program has no use-after-free, no double-free, and no data races.

That paragraph is the whole game. The rest of the language is utility on top of those rules.

Books that matter.

  • The Rust Programming Language ("The Book") — Steve Klabnik & Carol Nichols. The official, free, online. Start here. doc.rust-lang.org/book
  • Programming Rust (2nd ed) — Jim Blandy, Jason Orendorff, Leonora Tindall. O'Reilly. The most thorough reference; deeper than The Book.
  • Rust for Rustaceans — Jon Gjengset. Intermediate-to-advanced. Read after a few months when you want the next tier.
  • Zero to Production in Rust — Luca Palmieri. Builds a real web service end-to-end. The async/tokio/axum path made concrete.
  • The Rustonomicon — for unsafe Rust. Free, online. doc.rust-lang.org/nomicon
  • The Embedded Rust Book — for no_std targets. Free, online.

Courses & tutorials.

Documentation canon.

  • std library docsdoc.rust-lang.org/std. Searchable, exhaustive, with runnable examples.
  • The Referencedoc.rust-lang.org/reference. The language definition. Read when you want to know the rules precisely.
  • The Edition Guide — what's different in 2015 / 2018 / 2021 / 2024 editions.
  • The Cargo Book — Cargo's full reference.
  • docs.rs — auto-generated docs for every crate on crates.io.
  • The Async Book — async/await and futures explained.

Talks & videos.

  • "Rust: a language for the next 40 years" — Carol Nichols, 2019.
  • "Crust of Rust" — Jon Gjengset's deep-dive series on YouTube.
  • "Why is my Rust build so slow?" — recent compile-time analyses.
  • RustConf keynotes — Rust foundation events; the talks are recorded and freely available.
  • "Embedded Rust at Tesla" — production case studies in the wild.

Rust cheat sheet.

CommandWhat it does
cargo new <name>Scaffold a binary project (--lib for a library).
cargo runBuild + run in one step.
cargo build --releaseBuild optimized binary in target/release.
cargo testRun all #[test] functions.
cargo benchRun #[bench] functions (nightly) or criterion (stable).
cargo clippyLint — catches idiom issues and 100s of subtle bugs.
cargo fmtFormat with rustfmt — no options to argue about.
cargo doc --openGenerate docs and open in browser.
cargo add <crate>Add a dependency to Cargo.toml.
cargo updateRefresh Cargo.lock to latest compatible versions.
rustup updateUpdate the toolchain.
rustup component add rustfmt clippyAdd the standard ancillary tools.

Common mistakes.

  1. Mistake

    Fighting the borrow checker

    The first month feels like the compiler is wrong. It is not. Re-read the ownership chapter; the design usually wants to be different.

  2. Mistake

    Reaching for Rc<RefCell<T>>

    When the compiler says "no", clone() or restructure first. Rc<RefCell> is for shared mutable state — actually rare in well-designed code.

  3. Mistake

    Using .unwrap() in production

    Fine in tests and prototypes. In production, propagate with ? or handle explicitly. Panics in libraries are an API smell.

  4. Mistake

    Reaching for unsafe

    unsafe is the escape hatch. 99% of code should not need it. If you do, isolate it behind a safe API and document the invariants.

  5. Mistake

    Async without an executor

    async fn returns a Future. Calling it does nothing — you need .await inside an executor (tokio). Easy mistake; clear once seen.

  6. Mistake

    Building debug mode and benchmarking

    Always cargo build --release for performance numbers. Debug builds can be 100x slower.

Semicolony assets.

Cross-references from elsewhere on the site that reinforce the Rust path.

  • Operating systems — Rust's OS layer is what every async runtime sits on.
  • Computer architecture — Rust gets you closer to the silicon than any GC'd language; this path is what's underneath.
  • System design — Rust services in production share the same patterns as Go / Java.
  • Go — the other "modern systems" language. Sibling path with the same shape.

Roadmap — when ready.

  1. Week 1. The Rust Book chapters 1-10 + Rustlings. By the end: read any safe Rust program.
  2. Month 1. Build a CLI tool. Use clap for args, anyhow for errors. Publish to crates.io for the experience.
  3. Month 2. Build an HTTP service with axum + tokio + sqlx. Deploy. The full async path.
  4. Month 3. Pick one specialism — embedded, WASM, GPU (wgpu), audio (cpal), game (bevy), database (heavier).
  5. Year 1. Contribute to an open-source Rust crate. Read the standard library source. Try unsafe in a controlled context.

Keep going.

Rust pays back over time. Days 1–14 hurt. By month two, the compiler feels less like an adversary and more like a careful colleague. By month six, you'll find yourself wanting it in every project — and noticing what other languages let you get away with.