50 Rust Rules Every Specialist Should Follow
A master checklist across safety, API design, async, performance, and tooling. Use in reviews and onboarding.
How to Use This List
- Skim all 50 once, then deep-dive linked articles per gap.
- Tick rules your team enforces in CI or CONTRIBUTING.md.
- Revisit after toolchain or edition upgrades.
Safety and Correctness (1-10)
- Minimize
unsafescope - isolate in small modules with# Safetydocs. - Never
unwrapin library public API - returnResult. - Use
?for error propagation - avoid nestedmatchnoise. - Prefer
try_fromover lossyascasts - especially user input. - Run Miri/tests on unsafe code - catch UB in CI when feasible.
- Deny
unsafe_codein domain crates - single FFI crate exception documented. - Avoid
panic!for control flow - useResultorOption. - Validate invariants in constructors - illegal states unconstructable.
- Use
checked_addfor user-influenced arithmetic - or widen types. - Treat
#[deny(warnings)]seriously on toolchain bumps - fix, do not silence globally.
Ownership and Types (11-20)
- Newtype domain IDs -
UserIdnot bareu64. - Borrow before
clone- profile clones in hot paths. - Prefer
&stroverStringin arguments - takeimpl AsRef<str>when flexible. - Use
Cowat boundaries - borrow when possible, own when needed. - Enums over bool pairs -
enum State { Draft, Live }not two bools. - Typestate for critical protocols - when illegal transitions are costly.
- Implement
From/TryFrom- standard conversion traits. - RAII for resources - files, locks, guards.
- Avoid
Rc<RefCell>webs - redesign with ownership or channels. - Document
Send/Syncrequirements - especially for generic bounds.
Async and Concurrency (21-30)
- Do not block Tokio workers -
spawn_blockingfor sync I/O. - Use
tokio::sync::Mutexin async - notstd::sync::Mutexacross await. - Timeout external calls -
tokio::time::timeout. - Bound concurrency - semaphores on fan-out.
- Understand
Sendbounds on spawned tasks -'static+Send. - Graceful shutdown - signal + drain tasks.
- Channels for work distribution - backpressure aware.
- Atomics with correct ordering - not
SeqCstby default everywhere. - Avoid shared mutable globals -
OnceLockconfig instead. - Test async with
#[tokio::test]- fake time withpause.
Performance and Build (31-40)
- Measure release builds - profile before optimizing.
- Thin LTO for production - tune with data.
- Disable unused crate features - faster builds, smaller binaries.
- Commit
Cargo.lockfor apps - reproducible deploys. - Use
cargo clippy -D warnings- in CI. - Use
cargo fmt --check- zero style debate. - Criterion for hot path regressions - not guesswork.
- Avoid alloc in inner loops - reuse buffers.
- Prefer iterators until proven slow - zero-cost abstractions.
- Right-size connection pools - sqlx pool from load tests.
API, Errors, and Ecosystem (41-50)
- Follow Rust API Guidelines naming -
as_,to_,into_conventions. thiserrorin libraries,anyhowin binaries - workspace policy.- Structured errors with context -
error.source()chain. - Serde with
#[serde(deny_unknown_fields)]on external input - when safe. - Feature flags documented - README examples.
cargo auditon schedule - supply chain hygiene.- Doctests on public examples - docs stay honest.
- Integration tests on public API - not only private unit tests.
- ADR for architecture forks - record tradeoffs.
- Prefer std and well-maintained crates - audit before adding deps.
FAQs
All 50 mandatory?
Teams ratchet; start with safety, errors, CI (1-10, 41-48).
How enforce?
CI, clippy.toml disallowed methods, CODEOWNERS on unsafe crate.
Premium vs basic?
All listed rules are baseline specialist practice on this site.
Update cadence?
Review yearly with Rust edition and team incidents.
Junior vs senior?
Juniors focus 1-20; seniors own 21-50 and enforcement.
Link to deep dives?
See section articles: unsafe, async, performance, error rules.
Exceptions?
Document in ADR with owner and expiry date.
Embed in hiring?
Use as interview rubric for systems Rust roles.
vs clippy?
Rules align with clippy; clippy automates subset.
50 enough?
Starting point; team adds org-specific rules 51+.
Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.