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](rules/own-borrow-over-clone.md) - Prefer&Tborrowing over.clone() - [
own-slice-over-vec](rules/own-slice-over-vec.md) - Accept&[T]not&Vec<T>,&strnot&String - [
own-cow-conditional](rules/own-cow-conditional.md) - UseCow<'a, T>for conditional ownership - [
own-arc-shared](rules/own-arc-shared.md) - UseArc<T>for thread-safe shared ownership - [
own-rc-single-thread](rules/own-rc-single-thread.md) - UseRc<T>for single-threaded sharing - [
own-refcell-interior](rules/own-refcell-interior.md) - UseRefCell<T>for interior mutability (single-thread) - [
own-mutex-interior](rules/own-mutex-interior.md) - UseMutex<T>for interior mutability (multi-thread) - [
own-rwlock-readers](rules/own-rwlock-readers.md) - UseRwLock<T>when reads dominate writes - [
own-copy-small](rules/own-copy-small.md) - DeriveCopyfor small, trivial types - [
own-clone-explicit](rules/own-clone-explicit.md) - MakeCloneexplicit, avoid implicit copies - [
own-move-large](rules/own-move-large.md) - Move large data instead of cloning - [
own-lifetime-elision](rules/own-lifetime-elision.md) - Rely on lifetime elision when possible
2. Error Handling (CRITICAL)
- [
err-thiserror-lib](rules/err-thiserror-lib.md) - Usethiserrorfor library error types - [
err-anyhow-app](rules/err-anyhow-app.md) - Useanyhowfor application error handling - [
err-result-over-panic](rules/err-result-over-panic.md) - ReturnResult, don't panic on expected errors - [
err-context-chain](rules/err-context-chain.md) - Add context with.context()or.with_context() - [
err-no-unwrap-prod](rules/err-no-unwrap-prod.md) - Never use.unwrap()in production code - [
err-expect-bugs-only](rules/err-expect-bugs-only.md) - Use.expect()only for programming errors - [
err-question-mark](rules/err-question-mark.md) - Use?operator for clean propagation - [
err-from-impl](rules/err-from-impl.md) - Use#[from]for automatic error conversion - [
err-source-chain](rules/err-source-chain.md) - Use#[source]to chain underlying errors - [
err-lowercase-msg](rules/err-lowercase-msg.md) - Error messages: lowercase, no trailing punctuation - [
err-doc-errors](rules/err-doc-errors.md) - Document errors with# Errorssection - [
err-custom-type](rules/err-custom-type.md) - Create custom error types, notBox<dyn Error>
3. Memory Optimization (CRITICAL)
- [
mem-with-capacity](rules/mem-with-capacity.md) - Usewith_capacity()when size is known - [
mem-smallvec](rules/mem-smallvec.md) - UseSmallVecfor usually-small collections - [
mem-arrayvec](rules/mem-arrayvec.md) - UseArrayVecfor bounded-size collections - [
mem-box-large-variant](rules/mem-box-large-variant.md) - Box large enum variants to reduce type size - [
mem-boxed-slice](rules/mem-boxed-slice.md) - UseBox<[T]>instead ofVec<T>when fixed - [
mem-thinvec](rules/mem-thinvec.md) - UseThinVecfor often-empty vectors - [
mem-clone-from](rules/mem-clone-from.md) - Useclone_from()to reuse allocations - [
mem-reuse-collections](rules/mem-reuse-collections.md) - Reuse collections withclear()in loops - [
mem-avoid-format](rules/mem-avoid-format.md) - Avoidformat!()when string literals work - [
mem-write-over-format](rules/mem-write-over-format.md) - Usewrite!()instead offormat!() - [
mem-arena-allocator](rules/mem-arena-allocator.md) - Use arena allocators for batch allocations - [
mem-zero-copy](rules/mem-zero-copy.md) - Use zero-copy patterns with slices andBytes - [
mem-compact-string](rules/mem-compact-string.md) - UseCompactStringfor small string optimization - [
mem-smaller-integers](rules/mem-smaller-integers.md) - Use smallest integer type that fits - [
mem-assert-type-size](rules/mem-assert-type-size.md) - Assert hot type sizes to prevent regressions
4. API Design (HIGH)
- [
api-builder-pattern](rules/api-builder-pattern.md) - Use Builder pattern for complex construction - [
api-builder-must-use](rules/api-builder-must-use.md) - Add#[must_use]to builder types - [
api-newtype-safety](rules/api-newtype-safety.md) - Use newtypes for type-safe distinctions - [
api-typestate](rules/api-typestate.md) - Use typestate for compile-time state machines - [
api-sealed-trait](rules/api-sealed-trait.md) - Seal traits to prevent external implementations - [
api-extension-trait](rules/api-extension-trait.md) - Use extension traits to add methods to foreign types - [
api-parse-dont-validate](rules/api-parse-dont-validate.md) - Parse into validated types at boundaries - [
api-impl-into](rules/api-impl-into.md) - Acceptimpl Into<T>for flexible string inputs - [
api-impl-asref](rules/api-impl-asref.md) - Acceptimpl AsRef<T>for borrowed inputs - [
api-must-use](rules/api-must-use.md) - Add#[must_use]toResultreturning functions - [
api-non-exhaustive](rules/api-non-exhaustive.md) - Use#[non_exhaustive]for future-proof enums/structs - [
api-from-not-into](rules/api-from-not-into.md) - ImplementFrom, notInto(auto-derived) - [
api-default-impl](rules/api-default-impl.md) - ImplementDefaultfor sensible defaults - [
api-common-traits](rules/api-common-traits.md) - ImplementDebug,Clone,PartialEqeagerly - [
api-serde-optional](rules/api-serde-optional.md) - GateSerialize/Deserializebehind feature flag
5. Async/Await (HIGH)
- [
async-tokio-runtime](rules/async-tokio-runtime.md) - Use Tokio for production async runtime - [
async-no-lock-await](rules/async-no-lock-await.md) - Never holdMutex/RwLockacross.await - [
async-spawn-blocking](rules/async-spawn-blocking.md) - Usespawn_blockingfor CPU-intensive work - [
async-tokio-fs](rules/async-tokio-fs.md) - Usetokio::fsnotstd::fsin async code - [
async-cancellation-token](rules/async-cancellation-token.md) - UseCancellationTokenfor graceful shutdown - [
async-join-parallel](rules/async-join-parallel.md) - Usetokio::join!for parallel operations - [
async-try-join](rules/async-try-join.md) - Usetokio::try_join!for fallible parallel ops - [
async-select-racing](rules/async-select-racing.md) - Usetokio::select!for racing/timeouts - [
async-bounded-channel](rules/async-bounded-channel.md) - Use bounded channels for backpressure - [
async-mpsc-queue](rules/async-mpsc-queue.md) - Usempscfor work queues - [
async-broadcast-pubsub](rules/async-broadcast-pubsub.md) - Usebroadcastfor pub/sub patterns - [
async-watch-latest](rules