Rust Best Practices
Comprehensive guide for writing high-quality, idiomatic, and highly optimized Rust code. Contains 179 rules across 14 categories, prioritized by impact to guide LLMs in code generation and refactoring.
When to Apply
Reference these guidelines when:
- Writing new Rust functions, structs, or modules
- Implementing error handling or async code
- Designing public APIs for libraries
- Reviewing code for ownership/borrowing issues
- Optimizing memory usage or reducing allocations
- Tuning performance for hot paths
- Refactoring existing Rust code
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | Ownership & Borrowing | CRITICAL | own- | 12 |
| 2 | Error Handling | CRITICAL | err- | 12 |
| 3 | Memory Optimization | CRITICAL | mem- | 15 |
| 4 | API Design | HIGH | api- | 15 |
| 5 | Async/Await | HIGH | async- | 15 |
| 6 | Compiler Optimization | HIGH | opt- | 12 |
| 7 | Naming Conventions | MEDIUM | name- | 16 |
| 8 | Type Safety | MEDIUM | type- | 10 |
| 9 | Testing | MEDIUM | test- | 13 |
| 10 | Documentation | MEDIUM | doc- | 11 |
| 11 | Performance Patterns | MEDIUM | perf- | 11 |
| 12 | Project Structure | LOW | proj- | 11 |
| 13 | Clippy & Linting | LOW | lint- | 11 |
| 14 | Anti-patterns | REFERENCE | anti- | 15 |
Quick Reference
1. Ownership & Borrowing (CRITICAL)
own-borrow-over-clone- Prefer&Tborrowing over.clone()own-slice-over-vec- Accept&[T]not&Vec<T>,&strnot&Stringown-cow-conditional- UseCow<'a, T>for conditional ownershipown-arc-shared- UseArc<T>for thread-safe shared ownershipown-rc-single-thread- UseRc<T>for single-threaded sharingown-refcell-interior- UseRefCell<T>for interior mutability (single-thread)own-mutex-interior- UseMutex<T>for interior mutability (multi-thread)own-rwlock-readers- UseRwLock<T>when reads dominate writesown-copy-small- DeriveCopyfor small, trivial typesown-clone-explicit- MakeCloneexplicit, avoid implicit copiesown-move-large- Move large data instead of cloningown-lifetime-elision- Rely on lifetime elision when possible
2. Error Handling (CRITICAL)
err-thiserror-lib- Usethiserrorfor library error typeserr-anyhow-app- Useanyhowfor application error handlingerr-result-over-panic- ReturnResult, don't panic on expected errorserr-context-chain- Add context with.context()or.with_context()err-no-unwrap-prod- Never use.unwrap()in production codeerr-expect-bugs-only- Use.expect()only for programming errorserr-question-mark- Use?operator for clean propagationerr-from-impl- Use#[from]for automatic error conversionerr-source-chain- Use#[source]to chain underlying errorserr-lowercase-msg- Error messages: lowercase, no trailing punctuationerr-doc-errors- Document errors with# Errorssectionerr-custom-type- Create custom error types, notBox<dyn Error>
3. Memory Optimization (CRITICAL)
mem-with-capacity- Usewith_capacity()when size is knownmem-smallvec- UseSmallVecfor usually-small collectionsmem-arrayvec- UseArrayVecfor bounded-size collectionsmem-box-large-variant- Box large enum variants to reduce type sizemem-boxed-slice- UseBox<[T]>instead ofVec<T>when fixedmem-thinvec- UseThinVecfor often-empty vectorsmem-clone-from- Useclone_from()to reuse allocationsmem-reuse-collections- Reuse collections withclear()in loopsmem-avoid-format- Avoidformat!()when string literals workmem-write-over-format- Usewrite!()instead offormat!()mem-arena-allocator- Use arena allocators for batch allocationsmem-zero-copy- Use zero-copy patterns with slices andBytesmem-compact-string- UseCompactStringfor small string optimizationmem-smaller-integers- Use smallest integer type that fitsmem-assert-type-size- Assert hot type sizes to prevent regressions
4. API Design (HIGH)
api-builder-pattern- Use Builder pattern for complex constructionapi-builder-must-use- Add#[must_use]to builder typesapi-newtype-safety- Use newtypes for type-safe distinctionsapi-typestate- Use typestate for compile-time state machinesapi-sealed-trait- Seal traits to prevent external implementationsapi-extension-trait- Use extension traits to add methods to foreign typesapi-parse-dont-validate- Parse into validated types at boundariesapi-impl-into- Acceptimpl Into<T>for flexible string inputsapi-impl-asref- Acceptimpl AsRef<T>for borrowed inputsapi-must-use- Add#[must_use]toResultreturning functionsapi-non-exhaustive- Use#[non_exhaustive]for future-proof enums/structsapi-from-not-into- ImplementFrom, notInto(auto-derived)api-default-impl- ImplementDefaultfor sensible defaultsapi-common-traits- ImplementDebug,Clone,PartialEqeagerlyapi-serde-optional- GateSerialize/Deserializebehind feature flag
5. Async/Await (HIGH)
async-tokio-runtime- Use Tokio for production async runtimeasync-no-lock-await- Never holdMutex/RwLockacross.awaitasync-spawn-blocking- Usespawn_blockingfor CPU-intensive workasync-tokio-fs- Usetokio::fsnotstd::fsin async codeasync-cancellation-token- UseCancellationTokenfor graceful shutdownasync-join-parallel- Usetokio::join!for parallel operationsasync-try-join- Usetokio::try_join!for fallible parallel opsasync-select-racing- Usetokio::select!for racing/timeoutsasync-bounded-channel- Use bounded channels for backpressureasync-mpsc-queue- Usempscfor work queuesasync-broadcast-pubsub- Usebroadcastfor pub/sub patterns- [
async-watch-latest](rules