# Rust Code Review

> Rust Code review checklist and decision framework for Rust PRs, derived from rust-best-practices.

- Skill: `apollographql/rust-code-review` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add apollographql/rust-code-review`
- Raw SKILL.md: https://api.skillmd.com/api/skills/apollographql/rust-code-review/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: apollographql (https://skillmd.com/u/apollographql)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/apollographql/rust-code-review

---


# Rust Code Review

Use this for Rust review work where consistency, safety, and maintainability matter.

Follow ths standards in https://github.com/apollographql/rust-best-practices

## Mandatory pre-merge checks

- Ownership and data flow are intentional.
- Error handling is explicit and aligns with crate/binary boundaries.
- Clippy and format quality are clean in touched files.
- Performance changes are measured before acceptance.
- Public APIs are documented; docs match runtime behavior.
- Tests cover intended behavior and error paths.
- Unsafe or raw-pointer usage is justified and constrained.

## Severity matrix

- P0: unsafe memory bug, panic in recoverable production path, silent data corruption.
- P1: correctness bug, missing error propagation, invalid API contract.
- P2: likely performance regression, missing public API docs, flaky tests.
- P3: style/readability issues, avoidable clone/allocation, unnecessary complexity.

## Review skills

### Ownership-first coding

- Prefer borrowing (`&T`, `&mut T`) over cloning.
- Use `Clone` only when ownership is required or snapshots are explicitly needed.
- Treat unnecessary clones (especially in loops) as likely regressions.
- Reject `clone` on `Copy` types.

### Value vs reference

- Pass `Copy`/small POD types by value.
- Pass large heap-backed or non-trivial objects by reference.
- Surface ownership intent in function signatures.
- Use `Cow<'_, T>` when input may be borrowed or owned.

### Fallible control flow

- Use `let PATTERN = EXPR else { ... }` for expected early exits.
- Use `if let ... else` when divergence needs additional logic.
- Prefer `?` for bubbling errors.
- Avoid `unwrap`/`expect` in production except when impossible-by-design cases are documented.

### Allocation and allocation timing

- Prefer `_else` APIs to avoid eager allocation (`ok_or_else`, `map_or_else`, etc.).
- Keep iterator chains lazy; allocate only when required by terminal ops.
- Do not collect and allocate only to throw away data.

### Iterator vs loop

- Use iterator chains for data transformation and composition.
- Use `for` for early exits and side-effect-heavy or control-heavy loops.
- Require readable formatting; avoid long unreadable chains.

### Lints and static checks

- Run and fix warnings from:
  - `cargo clippy --all-targets --all-feature --locked -- -D warnings`
- Do not globally silence useful lints.
- Prefer `#[expect(clippy::...)]` with rationale instead of `#[allow(...)]` unless fully justified.

### Error discipline

- Libraries: prefer typed errors (`thiserror` and `#[from]` conversions).
- Binaries: `anyhow` acceptable, but keep context rich and actionable.
- Test both success and error behavior.

### Tests as behavior docs

- One behavior per test.
- One core assertion per test where possible.
- Names should be descriptive sentence-like statements.
- Prefer unit tests for internals, integration tests for public behavior.
- Use snapshot tests only for complex, stable structured outputs.

### Documentation and comments

- Use `///`/`//!` for API behavior and constraints.
- Use `//` for `why`, safety rationale, platform constraints, and assumptions.
- Remove stale comments; prefer smaller functions over narrative comments.
- Link TODOs to issues instead of leaving bare `TODO:`.

### Pointers and concurrency

- Prefer `&`/`&mut` before any heap pointer.
- Use `Arc` for cross-thread shared ownership; `Rc` for single-threaded.
- Use `Box` for recursive/heap allocation needs.
- Review raw pointer usage as unsafe boundaries with explicit invariants.

## Quick rejection triggers

- Unnecessary clones in hot paths.
- Unjustified `allow(clippy::...)`.
- Silent recovery from `Err` that discards root cause.
- Copying large types by value without a proof of intent.
- Comments that simply restate what code already expresses.
- TODOs without ownership/context.


