Foundations syntax and values Ownership move, borrow, lifetime Async Send, Sync, Future Systems unsafe, FFI, atomics API Design traits, typestate, semver Repo Work reading and contribution Compiler HIR, MIR, RFCs
The goal of these cards is reasoning, not slogan memorization. Read the answer aloud and make sure you can explain why it is true.
Question Answer
What false dichotomy does Rust challenge? That systems programmers must choose between low-level control and strong safety guarantees
Why is use-after-free more dangerous than an ordinary crash? It can expose stale memory, corrupt logic, or become an exploit primitive
What does double-free violate conceptually? Unique cleanup responsibility for a resource
Why are data races treated as undefined behavior in low-level models? Because unsynchronized concurrent mutation destroys reliable reasoning about program state
Why is iterator invalidation really an aliasing bug? A borrowed view assumes storage stability while mutation may reallocate or reorder it
Why did Rust reject a GC-first design? It would give up latency predictability, layout control, and the compile-time nature of ownership proofs
What does “pay at compile time” mean in practice? Accepting stricter modeling and slower learning in exchange for fewer runtime failures
What is zero-cost abstraction trying to preserve? The ability to write expressive high-level code without paying hidden runtime penalties
Why is “explicit over implicit” a safety principle in Rust? Hidden ownership, allocation, and failure paths make systems harder to reason about
Why is Rust relevant to security, not just performance? Memory safety failures are a dominant source of severe vulnerabilities
Why is “no null” more than a syntactic choice? It removes an invalid state from ordinary reference-like values
What makes Rust feel strict to beginners? It exposes invariants other languages often leave implicit until runtime
Question Answer
Why is cargo check the best default command during development? It validates types and borrowing quickly without full code generation
Why pin a toolchain with rust-toolchain.toml in teams? To reduce “works on my machine” drift in compiler behavior and lint/tool versions
Why does Cargo have both Cargo.toml and Cargo.lock? One describes intent and semver ranges; the other records the exact resolved dependency graph
What is the semantic difference between let and let mut? let promises stable binding value; let mut permits reassignment/mutation through that binding
Why is shadowing useful despite looking redundant? It can express type/value transformation while preserving a coherent variable name
Why does Rust distinguish const from static? const is inlined compile-time data; static is a single memory location with address identity
Why is () not the same thing as null? It is a real zero-sized type representing “no meaningful value,” not an invalid reference
Why do semicolons matter so much in Rust? They determine whether an expression’s value flows onward or is discarded into ()
Why is if more powerful in Rust than in C-like languages? It is an expression, so branches must agree on type and produce values
Why does match matter beyond convenience? Exhaustiveness checking makes unhandled states a compile-time error
Why does Option<T> improve API honesty? It forces absence to be modeled explicitly instead of smuggled through null-like values
Why is module visibility important early? Rust’s public API surface is deliberate and privacy-by-default shapes crate architecture
Question Answer
What is ownership really modeling? Responsibility for a resource and its cleanup
Why is borrowing necessary if ownership already exists? Because code often needs access without transferring cleanup responsibility
What is the shortest accurate statement of the borrow rule? Many shared borrows or one mutable borrow, but not both at once
Why are lifetimes relationships rather than durations? They express which references must not outlive which owners or other borrows
Why does stack vs heap matter to Rust reasoning? Because value size, movement, indirection, and ownership behavior often depend on storage strategy
Why can Copy types be duplicated implicitly? Their bitwise duplication is safe and they carry no custom destruction semantics
Why can’t a type be both Copy and Drop? Implicit duplication would make deterministic destruction ambiguous or duplicated
Why does borrow checking happen after desugaring/MIR-style reasoning? Control flow and real use sites are clearer there than in raw source syntax
What does NLL change for the programmer? Borrows end at last use rather than only at lexical scope end, reducing unnecessary conflicts
What is the beginner trap with lifetimes? Treating them like timers rather than proofs about reference relationships
Why is String versus &str foundational? It captures the split between owned text and borrowed text views
When should you restructure instead of fighting the borrow checker? When the current code expresses an unclear or conflicting ownership story
Question Answer
Why does Vec<T> expose both length and capacity? Because growth strategy and allocation planning matter to performance-sensitive code
Why prefer &str in function parameters over &String? It accepts more callers and expresses that only a borrowed string slice is needed
Why is the HashMap entry API so important? It lets you modify-or-initialize in one ownership-safe pass
What is the central performance virtue of iterators? They compose lazily and usually compile down to tight loops
When is a manual loop clearer than an iterator chain? When the control flow is stateful or the chain obscures intent
What determines whether a closure is Fn, FnMut, or FnOnce? How it captures and uses its environment
Why do blanket impls matter? They let capabilities propagate across many types without repetitive manual code
When are associated types better than generic parameters on a trait? When the output type is conceptually part of the trait’s contract
Why use thiserror in libraries? It preserves structured, explicit error vocabularies for downstream users
Why use anyhow in applications? It prioritizes ergonomic propagation and contextual reporting at the top level
What is the biggest risk of Rc<RefCell<T>>? It can turn design problems into runtime borrow failures and tangled ownership
Why do builders fit Rust well? They make staged, validated construction explicit without telescoping constructors
Question Answer
Why is thread::spawn usually associated with Send + 'static requirements? Spawned work may outlive the current stack frame and move to another thread
What does thread::scope relax? It allows threads to borrow from the surrounding stack safely within the scope
Why prefer message passing in many designs? Ownership transfer often clarifies concurrency more than shared mutable state
What does Send guarantee? That ownership can move safely across threads
What does Sync guarantee? That shared references can be used across threads safely
Why is Rc<T> not Send? Its reference count is not updated atomically
Why is Arc<Mutex<T>> common but not free? It buys shared mutable state with contention, locking, and API complexity costs
What is a future in Rust mechanically? A state machine that can be polled toward completion
Why doesn’t Rust standardize a single async runtime in the language? Runtime policy, scheduling, timers, and I/O backends are ecosystem choices rather than core language semantics
What does select! fundamentally do? It races branches and cancels or drops the losers according to their semantics
What is cancellation safety? The property that dropping a future partway through does not violate program invariants
Why does Pin show up around async code? Some futures become movement-sensitive after polling because of their internal state layout
Question Answer
Why does struct padding matter? It changes size, cache behavior, and FFI layout expectations
What is niche optimization in simple terms? Using invalid bit patterns of one representation to store enum discriminants for free
Why is Option<Box<T>> often the same size as Box<T>? The null pointer niche can encode None without extra storage
What does unsafe not turn off? Most of the type system and all ordinary syntax/type checking outside unsafe operations
What are the “unsafe superpowers” really about? Performing actions the compiler cannot prove safe, such as dereferencing raw pointers or calling foreign code
Why should unsafe code be hidden behind safe wrappers when possible? So the proof obligation is localized and downstream callers keep ordinary safety guarantees
Why do FFI boundaries need #[repr(C)] or careful layout thinking? Foreign code expects stable ABI/layout rules that Rust’s default layout does not promise
Why is variance relevant to advanced lifetime work? It determines how lifetimes and type parameters can be substituted safely
What is PhantomData used for? Encoding ownership, variance, or drop semantics that are not otherwise visible in fields
Why are atomics hard even in Rust? The type system helps with data races, but memory ordering is still a correctness proof you must make
Why benchmark with tools like criterion instead of ad hoc timing? Noise and measurement bias can make naive benchmarks lie
Why can compiler errors feel harder around advanced code? The abstractions encode more invariants, so the error often reflects a deeper modeling problem
Question Answer
What does a trait object contain conceptually? A data pointer plus metadata/vtable pointer
Why do object-safety rules exist? Dynamic dispatch needs a stable, runtime-usable method interface
What problem do GATs solve? They let associated types depend on lifetimes or generic parameters in more expressive ways
Why use a sealed trait? To prevent downstream crates from implementing a trait you need to evolve safely
When are macros the right tool? When the abstraction must transform syntax or generate repetitive type-aware code that functions cannot express
Why is macro hygiene important? It prevents generated code from accidentally capturing or colliding with surrounding names
What is the core idea of typestate? Encode valid states in types so invalid transitions fail at compile time
Why are newtypes so common in strong Rust APIs? They add domain meaning and prevent primitive-type confusion
What makes a semver break in Rust larger than many people expect? Type changes, trait impl changes, feature behavior, and visibility shifts can all alter downstream compilation
Why must feature flags usually be additive? Downstream dependency resolution assumes features unify rather than conflict destructively
When should a workspace split into multiple crates? When boundaries, compilation, publishability, or public API concerns justify real separation
Why is downstream composability a design goal? Good Rust libraries work with borrowing, traits, and error conversion instead of trapping users in one style
Question Answer
Why read Cargo.toml early in an unfamiliar repo? Dependencies reveal architecture, async/runtime choices, and likely entry points
Why are tests often better than docs for learning repo behavior? They show the intended API usage and the edge cases maintainers care about
Why should first PRs usually be boring? Small, focused changes are easier to review, safer to merge, and teach the repo’s norms faster
What makes a good first issue? Clear reproduction or scope, limited blast radius, and existing maintainers willing to guide
Why should you comment on an issue before coding? It avoids duplicate work and signals your proposed approach
What does a high-signal PR description contain? The problem, the approach, the changed files or behavior, and the verification steps
Why do unrelated refactors harm beginner PRs? They widen review scope and hide the actual behavior change
How do you trace a Rust code path effectively? Start at entry points, follow trait boundaries, inspect error types, and use tests to anchor behavior
Why are feature flags a repo-reading priority? They change which code exists and can explain “cannot find item” style confusion
What is the safest kind of first technical contribution after docs? A regression test or focused error-message improvement
Why do maintainers care so much about reproducible bug reports? Clear reproduction reduces reviewer load and increases trust in the fix
What does “read the invariant first” mean in repo work? Figure out what the codebase is trying to preserve before editing mechanics
Question Answer
Why distinguish AST, HIR, and MIR mentally? Different compiler phases reason about different normalized forms of the program
What does HIR buy the compiler? A desugared, high-level representation suitable for type and trait reasoning
What does MIR buy the compiler? Explicit control flow and value lifetimes for borrow checking and optimization
Why is monomorphization both good and costly? It yields zero-cost generic specialization but increases compile time and binary size
What is trait solving trying to answer? Whether the required capabilities can be proven from impls and bounds
Why does LLVM matter but not define Rust’s entire semantics? Rust lowers to LLVM, but ownership, borrowing, and many language rules are decided earlier
What is incremental compilation optimizing for? Faster rebuilds when only part of the crate graph changes
Why read RFCs as a learner? They reveal problem statements, rejected alternatives, and tradeoffs behind stable features
What is the purpose of nightly features? To experiment before stabilization and collect real-world feedback
Why does Rust stabilize carefully? The language promises long-term compatibility, so rushed design costs everyone
What makes async/await a useful RFC case study? It shows ergonomics, zero-cost goals, and compiler/runtime boundary tradeoffs colliding in public
Why does participating in discussions help even before you propose anything? It trains you to think in terms of constraints and tradeoffs instead of personal preference
Question Answer
Why is daily repetition more valuable than occasional marathons? Rust skill is largely pattern recognition and invariant recall under pressure
What should the first three months optimize for? Ownership fluency, reading compiler errors, and finishing small complete projects
Why build both a CLI and a service early? They exercise different API, error, and runtime patterns
Why read real repos before you feel ready? Real code is where abstractions become memorable and contextual
What is a strong sign you’re ready for deeper async work? You can explain Send, ownership across tasks, and basic cancellation without cargo-culting
Why publish a crate before aiming at compiler work? Library design and semver discipline teach habits that matter everywhere in Rust
What does “contribute regularly to a few repos” teach better than drive-by PRs? It teaches architecture, social norms, and long-term API consequences
Why should flashcards test reasoning rather than slogans? Rust problems are usually about choosing the right model, not recalling vocabulary
What is the most important self-question after any compiler error? “What ownership, capability, or lifetime story did I tell badly?”
Why is reviewer trust part of Rust mastery? Strong Rust engineers are judged by how safely and clearly they change real systems
What does genuine mastery look like? Predicting invariants, navigating unfamiliar code, and making correct changes with low drama
What is the long-term payoff of learning Rust deeply? The ability to build and review systems code with unusually strong correctness intuition
These appendices are reference tools, not substitutes for the chapters. Use them to compress the material after you have worked through the ideas in context.