Review checklist
Use this page next to the diff. Work from the top: the first groups find the problems that cost the most. Each item links to the smell or concept that explains it. The page prints on two sides of paper (use your browser’s print command).
1. Build gate
Section titled “1. Build gate”-
cargo fmt --checkpasses. -
cargo clippy --all-targets -- -D warningspasses. See Tooling. -
cargo testpasses, and the new code has tests. - No new
#[allow(...)]without a comment that gives the reason (S25).
2. Failure behavior
Section titled “2. Failure behavior”- Every
unwrap()andexpect()outside tests has a reason that it cannot fail, written in theexpectmessage (S02). - No
panic!for errors that can happen in normal use: bad input, missing files, network errors (S36). - No indexing
v[i]or slicings[a..b]on input data without a check (S24). - No ignored
Result:let _ = ...,.ok();, or.unwrap_or_default()that hides a failure (S08). - Error types are enums or typed errors, not
String(S07). - Errors keep their cause and add context: file name, ID, line number (S09).
- Numeric conversions with
ascannot truncate or change sign (S23).
3. Ownership and copies
Section titled “3. Ownership and copies”- Each
.clone()has a reason. Look hardest in loops and on collections (S01). - Functions that only read take
&str,&[T], or&T, notString,Vec<T>,&String, or&Vec<T>(S05, S06). - No
Rc<RefCell<T>>object graph that copies a Java design (S03). - No
Arc<Mutex<T>>in code that one thread uses (S04). - See Ownership and moves, Borrowing, and Clone and Copy.
4. Types and design
Section titled “4. Types and design”- States are enums, not
boolflags, string constants, or manyOptionfields (S15, S17). - No wildcard
_ =>arm on an enum that the crate owns (S16). - IDs and units have their own types where a mix-up is possible (S37).
- Traits are small. No trait hierarchy that copies a Java class hierarchy (S13).
-
Box<dyn Trait>only where the set of types is open (S22). - Only the necessary items are
pub(S38). - See Structs and impl, Traits vs interfaces, and Enums and pattern matching.
5. Concurrency, async, and unsafe
Section titled “5. Concurrency, async, and unsafe”- No blocking calls (
std::fs,std::thread::sleep, heavy CPU work) insideasynccode (S18). - No
std::sync::Mutexguard held across.await(S19). - Spawned tasks and channels are bounded (S34).
- No
static mutor other global mutable state (S29). - Every
unsafeblock has a// SAFETY:comment, and the reason is convincing. In application code, ask whyunsafeis necessary at all (S20). - See Threads and shared state, Async, and Unsafe and FFI.
6. Dependencies
Section titled “6. Dependencies”- Every crate exists on crates.io and does what the code expects. Check each new API on docs.rs (S26).
- Crates are maintained, versions are current, and default features are not pulling in large code that the project does not use (S28).
- No wildcard versions (
*).Cargo.lockis committed for applications. - See Modules, crates, and Cargo.
7. Readability
Section titled “7. Readability”- Iterator chains are short enough to read. A
forloop is fine when it is clearer (S10, S11). - Nesting is shallow.
?andlet ... elsereplace nestedmatchandif let. - Comments explain why, not what.
- See Iterators vs streams.