Rust Code Reviewer
Review Rust code targeting the specific failure modes that AI-generated and human-written Rust most commonly gets wrong. Not a generic code review — Rust-specific.
Review Checklist (ordered by severity)
1. Unsafe Code Audit (critical)
First: is unsafe even necessary?
- •FFI calls → yes, required
- •Raw pointer deref → yes, but can it be restructured to avoid raw pointers?
- •Mutable statics → yes, but consider
OnceCell,LazyLock, or atomics instead - •Implementing
Send/Sync→ yes, but verify the type genuinely satisfies the contract - •Bypassing borrow checker → no. The design is wrong. Redesign it.
- •Performance → maybe. Must have measured proof.
For every unsafe block that IS necessary:
- •
// SAFETY:comment explains why invariants hold (not just "this is safe") - • Block scope is minimal
- • Pointer validity: non-null, points to allocated memory, properly aligned, valid bit pattern
- • Aliasing: no simultaneous
&Tand&mut Tto same data, no two&mut Tto same data - • Initialization: memory initialized before read,
MaybeUninitused correctly - • Type invariants: transmutes maintain validity,
#[repr(C)]where layout matters, UTF-8 valid for strings - • Concurrency:
Send/Synccontracts genuine, no data races, correct atomic ordering - • Drop safety:
drop_in_placeexactly once, no double-free, correct allocator - • Encapsulation: unsafe wrapped behind a safe API, invariants enforced by construction
rust
// BAD: // SAFETY: this is fine // BAD: // SAFETY: we know the pointer is valid // GOOD: // SAFETY: `ptr` was obtained from `Box::into_raw` in `new()` and has not // been freed since. The Box was allocated with the global allocator, same // as used by `Box::from_raw`. Non-null guaranteed by Box.
2. Lifetime Correctness
- • Lifetime annotations trace actual data flow, not guessed
- • No hidden
'staticassumptions that break callers - • Struct lifetimes match actual borrow durations of their fields
- • No unnecessary lifetime parameters (elision handles most cases)
- • Self-referential patterns avoided or correctly handled with
Pin
3. Async Correctness
- • No blocking operations (
std::fs,std::net,thread::sleep) in async fns - • No
std::sync::MutexGuardheld across.awaitpoints - • Spawned tasks: all captured data is
Send + 'static - • No mixing async runtimes (tokio vs async-std)
- • Cancellation safety considered for futures that may be dropped mid-await
- • Trait objects: boxed with correct
Send/lifetime bounds - •
?works across.await(error types compatible)
4. Ownership Smells
- • Excessive
.clone(): each one should have a reason, not a borrow-checker escape - •
Rc/Arcoveruse: shared ownership should be intentional - • Unnecessary
Box<dyn Trait>: could this beimpl Traitinstead? - •
Stringwhere&strsuffices in function params (and vice versa in struct fields)
5. Error Handling
- • No
unwrap()/expect()on fallible paths (network, IO, user input, parsing) - •
unwrap()acceptable in: tests, provably infallible cases with comment, earlymain()setup - • Error types implement
std::error::Error+Display - • Error context preserved across conversions (
.context()ormap_err) - •
?used consistently
6. API Design
- • Rust conventions:
new(),builder(),into_*/as_*/to_*naming - •
#[must_use]where ignoring return value is likely a bug - • Standard trait impls:
Debug,Display,Clone,PartialEqwhere appropriate - • Functions accept borrows (
&str,&[T],&Path) when they don't need ownership
7. Idiomatic Patterns
- • Iterators over manual indexing
- • Pattern matching over if-else chains on enums
- •
if let/let elsefor single-variant matches - • No C-style
for i in 0..v.len() { v[i] }— usefor item in &v - •
Defaultderive/impl where a zero value makes sense
8. Dependencies & Imports
- • Imports resolve to actual paths in the dependency tree
- • No unused imports
- • No deprecated API usage
- • Feature flags documented if enabling optional crate features
Output Format
Present findings grouped by severity:
- •Blocking — must fix (unsafe soundness holes, lifetime bugs, compilation errors)
- •Should fix — correctness or significant quality (error handling, ownership smells, async pitfalls)
- •Suggestions — idiomatic improvements, style (won't break anything)