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 &T borrowing over .clone()
own-slice-over-vec - Accept &[T] not &Vec<T>, &str not &String
own-cow-conditional - Use Cow<'a, T> for conditional ownership
own-arc-shared - Use Arc<T> for thread-safe shared ownership
own-rc-single-thread - Use Rc<T> for single-threaded sharing
own-refcell-interior - Use RefCell<T> for interior mutability (single-thread)
own-mutex-interior - Use Mutex<T> for interior mutability (multi-thread)
own-rwlock-readers - Use RwLock<T> when reads dominate writes
own-copy-small - Derive Copy for small, trivial types
own-clone-explicit - Make Clone explicit, avoid implicit copies
own-move-large - Move large data instead of cloning
own-lifetime-elision - Rely on lifetime elision when possible
2. Error Handling (CRITICAL)
err-thiserror-lib - Use thiserror for library error types
err-anyhow-app - Use anyhow for application error handling
err-result-over-panic - Return Result, don't panic on expected errors
err-context-chain - Add context with .context() or .with_context()
err-no-unwrap-prod - Never use .unwrap() in production code
err-expect-bugs-only - Use .expect() only for programming errors
err-question-mark - Use ? operator for clean propagation
err-from-impl - Use #[from] for automatic error conversion
err-source-chain - Use #[source] to chain underlying errors
err-lowercase-msg - Error messages: lowercase, no trailing punctuation
err-doc-errors - Document errors with # Errors section
err-custom-type - Create custom error types, not Box<dyn Error>
3. Memory Optimization (CRITICAL)
mem-with-capacity - Use with_capacity() when size is known
mem-smallvec - Use SmallVec for usually-small collections
mem-arrayvec - Use ArrayVec for bounded-size collections
mem-box-large-variant - Box large enum variants to reduce type size
mem-boxed-slice - Use Box<[T]> instead of Vec<T> when fixed
mem-thinvec - Use ThinVec for often-empty vectors
mem-clone-from - Use clone_from() to reuse allocations
mem-reuse-collections - Reuse collections with clear() in loops
mem-avoid-format - Avoid format!() when string literals work
mem-write-over-format - Use write!() instead of format!()
mem-arena-allocator - Use arena allocators for batch allocations
mem-zero-copy - Use zero-copy patterns with slices and Bytes
mem-compact-string - Use CompactString for small string optimization
mem-smaller-integers - Use smallest integer type that fits
mem-assert-type-size - Assert hot type sizes to prevent regressions
4. API Design (HIGH)
api-builder-pattern - Use Builder pattern for complex construction
api-builder-must-use - Add #[must_use] to builder types
api-newtype-safety - Use newtypes for type-safe distinctions
api-typestate - Use typestate for compile-time state machines
api-sealed-trait - Seal traits to prevent external implementations
api-extension-trait - Use extension traits to add methods to foreign types
api-parse-dont-validate - Parse into validated types at boundaries
api-impl-into - Accept impl Into<T> for flexible string inputs
api-impl-asref - Accept impl AsRef<T> for borrowed inputs
api-must-use - Add #[must_use] to Result returning functions
api-non-exhaustive - Use #[non_exhaustive] for future-proof enums/structs
api-from-not-into - Implement From, not Into (auto-derived)
api-default-impl - Implement Default for sensible defaults
api-common-traits - Implement Debug, Clone, PartialEq eagerly
api-serde-optional - Gate Serialize/Deserialize behind feature flag
5. Async/Await (HIGH)
async-tokio-runtime - Use Tokio for production async runtime
async-no-lock-await - Never hold Mutex/RwLock across .await
async-spawn-blocking - Use spawn_blocking for CPU-intensive work
async-tokio-fs - Use tokio::fs not std::fs in async code
async-cancellation-token - Use CancellationToken for graceful shutdown
async-join-parallel - Use tokio::join! for parallel operations
async-try-join - Use tokio::try_join! for fallible parallel ops
async-select-racing - Use tokio::select! for racing/timeouts
async-bounded-channel - Use bounded channels for backpressure
async-mpsc-queue - Use mpsc for work queues
async-broadcast-pubsub - Use broadcast for pub/sub patterns
async-watch-latest - Use watch for latest-value sharing
async-oneshot-response - Use oneshot for request/response
async-joinset-structured - Use JoinSet for dynamic task groups
async-clone-before-await - Clone data before await, release locks
6. Compiler Optimization (HIGH)
opt-inline-small - Use #[inline] for small hot functions
opt-inline-always-rare - Use #[inline(always)] sparingly
opt-inline-never-cold - Use #[inline(never)] for cold paths
opt-cold-unlikely - Use #[cold] for error/unlikely paths
opt-likely-hint - Use likely()/unlikely() for branch hints
opt-lto-release - Enable LTO in release builds
opt-codegen-units - Use codegen-units = 1 for max optimization
opt-pgo-profile - Use PGO for production builds
opt-target-cpu - Set target-cpu=native for local builds
opt-bounds-check - Use iterators to avoid bounds checks
opt-simd-portable - Use portable SIMD for data-parallel ops
opt-cache-friendly - Design cache-friendly data layouts (SoA)
7. Naming Conventions (MEDIUM)
name-types-camel - Use UpperCamelCase for types, traits, enums
name-variants-camel - Use UpperCamelCase for enum variants
name-funcs-snake - Use snake_case for functions, methods, modules
name-consts-screaming - Use SCREAMING_SNAKE_CASE for constants/statics
name-lifetime-short - Use short lowercase lifetimes: 'a, 'de, 'src
name-type-param-single - Use single uppercase for type params: T, E, K, V
name-as-free - as_ prefix: free reference conversion
name-to-expensive - to_ prefix: expensive conversion
name-into-ownership - into_ prefix: ownership transfer
name-no-get-prefix - No get_ prefix for simple getters
name-is-has-bool - Use is_, has_, can_ for boolean methods
name-iter-convention - Use iter/iter_mut/into_iter for iterators
name-iter-method - Name iterator methods consistently
name-iter-type-match - Iterator type names match method
name-acronym-word - Treat acronyms as words: Uuid not UUID
name-crate-no-rs - Crate names: no -rs suffix
8. Type Safety (MEDIUM)
type-newtype-ids - Wrap IDs in newtypes: UserId(u64)
type-newtype-validated - Newtypes for validated data: Email, Url
type-enum-states - Use enums for mutually exclusive states
type-option-nullable - Use Option<T> for nullable values
type-result-fallible - Use Result<T, E> for fallible operations
type-phantom-marker - Use PhantomData<T> for type-level markers
type-never-diverge - Use ! type for functions that never return
type-generic-bounds - Add trait bounds only where needed
type-no-stringly - Avoid stringly-typed APIs, use enums/newtypes
type-repr-transparent - Use #[repr(transparent)] for FFI newtypes
9. Testing (MEDIUM)
test-cfg-test-module - Use #[cfg(test)] mod tests { }
test-use-super - Use use super::*; in test modules
test-integration-dir - Put integration tests in tests/ directory
test-descriptive-names - Use descriptive test names
test-arrange-act-assert - Structure tests as arrange/act/assert
test-proptest-properties - Use proptest for property-based testing
test-mockall-mocking - Use mockall for trait mocking
test-mock-traits - Use traits for dependencies to enable mocking
test-fixture-raii - Use RAII pattern (Drop) for test cleanup
test-tokio-async - Use #[tokio::test] for async tests
test-should-panic - Use #[should_panic] for panic tests
test-criterion-bench - Use criterion for benchmarking
test-doctest-examples - Keep doc examples as executable tests
10. Documentation (MEDIUM)
doc-all-public - Document all public items with ///
doc-module-inner - Use //! for module-level documentation
doc-examples-section - Include # Examples with runnable code
doc-errors-section - Include # Errors for fallible functions
doc-panics-section - Include # Panics for panicking functions
doc-safety-section - Include # Safety for unsafe functions
doc-question-mark - Use ? in examples, not .unwrap()
doc-hidden-setup - Use # prefix to hide example setup code
doc-intra-links - Use intra-doc links: [Vec]
doc-link-types - Link related types and functions in docs
doc-cargo-metadata - Fill Cargo.toml metadata
11. Performance Patterns (MEDIUM)
perf-iter-over-index - Prefer iterators over manual indexing
perf-iter-lazy - Keep iterators lazy, collect() only when needed
perf-collect-once - Don't collect() intermediate iterators
perf-entry-api - Use entry() API for map insert-or-update
perf-drain-reuse - Use drain() to reuse allocations
perf-extend-batch - Use extend() for batch insertions
perf-chain-avoid - Avoid chain() in hot loops
perf-collect-into - Use collect_into() for reusing containers
perf-black-box-bench - Use black_box() in benchmarks
perf-release-profile - Optimize release profile settings
perf-profile-first - Profile before optimizing
12. Project Structure (LOW)
proj-lib-main-split - Keep main.rs minimal, logic in lib.rs
proj-mod-by-feature - Organize modules by feature, not type
proj-flat-small - Keep small projects flat
proj-mod-rs-dir - Use mod.rs for multi-file modules
proj-pub-crate-internal - Use pub(crate) for internal APIs
proj-pub-super-parent - Use pub(super) for parent-only visibility
proj-pub-use-reexport - Use pub use for clean public API
proj-prelude-module - Create prelude module for common imports
proj-bin-dir - Put multiple binaries in src/bin/
proj-workspace-large - Use workspaces for large projects
proj-workspace-deps - Use workspace dependency inheritance
13. Clippy & Linting (LOW)
lint-deny-correctness - #![deny(clippy::correctness)]
lint-warn-suspicious - #![warn(clippy::suspicious)]
lint-warn-style - #![warn(clippy::style)]
lint-warn-complexity - #![warn(clippy::complexity)]
lint-warn-perf - #![warn(clippy::perf)]
lint-pedantic-selective - Enable clippy::pedantic selectively
lint-missing-docs - #![warn(missing_docs)]
lint-unsafe-doc - #![warn(clippy::undocumented_unsafe_blocks)]
lint-cargo-metadata - #![warn(clippy::cargo)] for published crates
lint-rustfmt-check - Run cargo fmt --check in CI
lint-workspace-lints - Configure lints at workspace level
14. Anti-patterns (REFERENCE)
anti-unwrap-abuse - Don't use .unwrap() in production code
anti-expect-lazy - Don't use .expect() for recoverable errors
anti-clone-excessive - Don't clone when borrowing works
anti-lock-across-await - Don't hold locks across .await
anti-string-for-str - Don't accept &String when &str works
anti-vec-for-slice - Don't accept &Vec<T> when &[T] works
anti-index-over-iter - Don't use indexing when iterators work
anti-panic-expected - Don't panic on expected/recoverable errors
anti-empty-catch - Don't use empty if let Err(_) = ... blocks
anti-over-abstraction - Don't over-abstract with excessive generics
anti-premature-optimize - Don't optimize before profiling
anti-type-erasure - Don't use Box<dyn Trait> when impl Trait works
anti-format-hot-path - Don't use format!() in hot paths
anti-collect-intermediate - Don't collect() intermediate iterators
anti-stringly-typed - Don't use strings for structured data
Recommended Cargo.toml Settings
Standalone project
[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1
panic = "abort"
strip = true
[profile.bench]
inherits = "release"
debug = true
strip = false
[profile.dev]
opt-level = 0
debug = true
[profile.dev.package."*"]
opt-level = 3 # Optimize dependencies in dev
Workspace
[workspace]
members = ["crates/*"]
resolver = "2"
[workspace.package]
edition = "2024"
rust-version = "1.85"
license = "MIT"
[workspace.dependencies]
# Pin shared dependencies here
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
thiserror = "2"
anyhow = "1"
[workspace.lints.rust]
unsafe_code = "forbid"
[workspace.lints.clippy]
correctness = { level = "deny", priority = -1 }
suspicious = { level = "warn", priority = -1 }
style = { level = "warn", priority = -1 }
complexity = { level = "warn", priority = -1 }
perf = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1
panic = "abort"
strip = true
[profile.bench]
inherits = "release"
debug = true
strip = false
[profile.dev]
opt-level = 0
debug = true
[profile.dev.package."*"]
opt-level = 3 # Optimize dependencies in dev
Member crates inherit from the workspace:
[package]
name = "my-crate"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
[dependencies]
tokio = { workspace = true }
serde = { workspace = true }
[lints]
workspace = true
How to Use
This skill provides rule identifiers for quick reference. When generating or reviewing Rust code:
- Check relevant category based on task type
- Apply rules with matching prefix
- Prioritize CRITICAL > HIGH > MEDIUM > LOW
- Read rule files in
rules/ for detailed examples
Rule Application by Task
| Task |
Primary Categories |
| New function |
own-, err-, name- |
| New struct/API |
api-, type-, doc- |
| Async code |
async-, own- |
| Error handling |
err-, api- |
| Memory optimization |
mem-, own-, perf- |
| Performance tuning |
opt-, mem-, perf- |
| Code review |
anti-, lint- |
Sources
This skill synthesizes best practices from:
1---2name: rust-skills3description: Comprehensive Rust coding guidelines with 179 rules across 14 categories. Use when writing, reviewing, or refactoring Rust code. Covers ownership, error handling, async patterns, API design, memory optimization, performance, testing, and common anti-patterns. Invoke with /rust-skills.4license: MIT5---67# Rust Best Practices89Comprehensive 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.1011## When to Apply1213Reference these guidelines when:14- Writing new Rust functions, structs, or modules15- Implementing error handling or async code16- Designing public APIs for libraries17- Reviewing code for ownership/borrowing issues18- Optimizing memory usage or reducing allocations19- Tuning performance for hot paths20- Refactoring existing Rust code2122## Rule Categories by Priority2324| Priority | Category | Impact | Prefix | Rules |25|----------|----------|--------|--------|-------|26| 1 | Ownership & Borrowing | CRITICAL | `own-` | 12 |27| 2 | Error Handling | CRITICAL | `err-` | 12 |28| 3 | Memory Optimization | CRITICAL | `mem-` | 15 |29| 4 | API Design | HIGH | `api-` | 15 |30| 5 | Async/Await | HIGH | `async-` | 15 |31| 6 | Compiler Optimization | HIGH | `opt-` | 12 |32| 7 | Naming Conventions | MEDIUM | `name-` | 16 |33| 8 | Type Safety | MEDIUM | `type-` | 10 |34| 9 | Testing | MEDIUM | `test-` | 13 |35| 10 | Documentation | MEDIUM | `doc-` | 11 |36| 11 | Performance Patterns | MEDIUM | `perf-` | 11 |37| 12 | Project Structure | LOW | `proj-` | 11 |38| 13 | Clippy & Linting | LOW | `lint-` | 11 |39| 14 | Anti-patterns | REFERENCE | `anti-` | 15 |4041---4243## Quick Reference4445### 1. Ownership & Borrowing (CRITICAL)4647- [`own-borrow-over-clone`](rules/own-borrow-over-clone.md) - Prefer `&T` borrowing over `.clone()`48- [`own-slice-over-vec`](rules/own-slice-over-vec.md) - Accept `&[T]` not `&Vec<T>`, `&str` not `&String`49- [`own-cow-conditional`](rules/own-cow-conditional.md) - Use `Cow<'a, T>` for conditional ownership50- [`own-arc-shared`](rules/own-arc-shared.md) - Use `Arc<T>` for thread-safe shared ownership51- [`own-rc-single-thread`](rules/own-rc-single-thread.md) - Use `Rc<T>` for single-threaded sharing52- [`own-refcell-interior`](rules/own-refcell-interior.md) - Use `RefCell<T>` for interior mutability (single-thread)53- [`own-mutex-interior`](rules/own-mutex-interior.md) - Use `Mutex<T>` for interior mutability (multi-thread)54- [`own-rwlock-readers`](rules/own-rwlock-readers.md) - Use `RwLock<T>` when reads dominate writes55- [`own-copy-small`](rules/own-copy-small.md) - Derive `Copy` for small, trivial types56- [`own-clone-explicit`](rules/own-clone-explicit.md) - Make `Clone` explicit, avoid implicit copies57- [`own-move-large`](rules/own-move-large.md) - Move large data instead of cloning58- [`own-lifetime-elision`](rules/own-lifetime-elision.md) - Rely on lifetime elision when possible5960### 2. Error Handling (CRITICAL)6162- [`err-thiserror-lib`](rules/err-thiserror-lib.md) - Use `thiserror` for library error types63- [`err-anyhow-app`](rules/err-anyhow-app.md) - Use `anyhow` for application error handling64- [`err-result-over-panic`](rules/err-result-over-panic.md) - Return `Result`, don't panic on expected errors65- [`err-context-chain`](rules/err-context-chain.md) - Add context with `.context()` or `.with_context()`66- [`err-no-unwrap-prod`](rules/err-no-unwrap-prod.md) - Never use `.unwrap()` in production code67- [`err-expect-bugs-only`](rules/err-expect-bugs-only.md) - Use `.expect()` only for programming errors68- [`err-question-mark`](rules/err-question-mark.md) - Use `?` operator for clean propagation69- [`err-from-impl`](rules/err-from-impl.md) - Use `#[from]` for automatic error conversion70- [`err-source-chain`](rules/err-source-chain.md) - Use `#[source]` to chain underlying errors71- [`err-lowercase-msg`](rules/err-lowercase-msg.md) - Error messages: lowercase, no trailing punctuation72- [`err-doc-errors`](rules/err-doc-errors.md) - Document errors with `# Errors` section73- [`err-custom-type`](rules/err-custom-type.md) - Create custom error types, not `Box<dyn Error>`7475### 3. Memory Optimization (CRITICAL)7677- [`mem-with-capacity`](rules/mem-with-capacity.md) - Use `with_capacity()` when size is known78- [`mem-smallvec`](rules/mem-smallvec.md) - Use `SmallVec` for usually-small collections79- [`mem-arrayvec`](rules/mem-arrayvec.md) - Use `ArrayVec` for bounded-size collections80- [`mem-box-large-variant`](rules/mem-box-large-variant.md) - Box large enum variants to reduce type size81- [`mem-boxed-slice`](rules/mem-boxed-slice.md) - Use `Box<[T]>` instead of `Vec<T>` when fixed82- [`mem-thinvec`](rules/mem-thinvec.md) - Use `ThinVec` for often-empty vectors83- [`mem-clone-from`](rules/mem-clone-from.md) - Use `clone_from()` to reuse allocations84- [`mem-reuse-collections`](rules/mem-reuse-collections.md) - Reuse collections with `clear()` in loops85- [`mem-avoid-format`](rules/mem-avoid-format.md) - Avoid `format!()` when string literals work86- [`mem-write-over-format`](rules/mem-write-over-format.md) - Use `write!()` instead of `format!()` 87- [`mem-arena-allocator`](rules/mem-arena-allocator.md) - Use arena allocators for batch allocations88- [`mem-zero-copy`](rules/mem-zero-copy.md) - Use zero-copy patterns with slices and `Bytes`89- [`mem-compact-string`](rules/mem-compact-string.md) - Use `CompactString` for small string optimization90- [`mem-smaller-integers`](rules/mem-smaller-integers.md) - Use smallest integer type that fits91- [`mem-assert-type-size`](rules/mem-assert-type-size.md) - Assert hot type sizes to prevent regressions9293### 4. API Design (HIGH)9495- [`api-builder-pattern`](rules/api-builder-pattern.md) - Use Builder pattern for complex construction96- [`api-builder-must-use`](rules/api-builder-must-use.md) - Add `#[must_use]` to builder types97- [`api-newtype-safety`](rules/api-newtype-safety.md) - Use newtypes for type-safe distinctions98- [`api-typestate`](rules/api-typestate.md) - Use typestate for compile-time state machines99- [`api-sealed-trait`](rules/api-sealed-trait.md) - Seal traits to prevent external implementations100- [`api-extension-trait`](rules/api-extension-trait.md) - Use extension traits to add methods to foreign types101- [`api-parse-dont-validate`](rules/api-parse-dont-validate.md) - Parse into validated types at boundaries102- [`api-impl-into`](rules/api-impl-into.md) - Accept `impl Into<T>` for flexible string inputs103- [`api-impl-asref`](rules/api-impl-asref.md) - Accept `impl AsRef<T>` for borrowed inputs104- [`api-must-use`](rules/api-must-use.md) - Add `#[must_use]` to `Result` returning functions105- [`api-non-exhaustive`](rules/api-non-exhaustive.md) - Use `#[non_exhaustive]` for future-proof enums/structs106- [`api-from-not-into`](rules/api-from-not-into.md) - Implement `From`, not `Into` (auto-derived)107- [`api-default-impl`](rules/api-default-impl.md) - Implement `Default` for sensible defaults108- [`api-common-traits`](rules/api-common-traits.md) - Implement `Debug`, `Clone`, `PartialEq` eagerly109- [`api-serde-optional`](rules/api-serde-optional.md) - Gate `Serialize`/`Deserialize` behind feature flag110111### 5. Async/Await (HIGH)112113- [`async-tokio-runtime`](rules/async-tokio-runtime.md) - Use Tokio for production async runtime114- [`async-no-lock-await`](rules/async-no-lock-await.md) - Never hold `Mutex`/`RwLock` across `.await`115- [`async-spawn-blocking`](rules/async-spawn-blocking.md) - Use `spawn_blocking` for CPU-intensive work116- [`async-tokio-fs`](rules/async-tokio-fs.md) - Use `tokio::fs` not `std::fs` in async code117- [`async-cancellation-token`](rules/async-cancellation-token.md) - Use `CancellationToken` for graceful shutdown118- [`async-join-parallel`](rules/async-join-parallel.md) - Use `tokio::join!` for parallel operations119- [`async-try-join`](rules/async-try-join.md) - Use `tokio::try_join!` for fallible parallel ops120- [`async-select-racing`](rules/async-select-racing.md) - Use `tokio::select!` for racing/timeouts121- [`async-bounded-channel`](rules/async-bounded-channel.md) - Use bounded channels for backpressure122- [`async-mpsc-queue`](rules/async-mpsc-queue.md) - Use `mpsc` for work queues123- [`async-broadcast-pubsub`](rules/async-broadcast-pubsub.md) - Use `broadcast` for pub/sub patterns124- [`async-watch-latest`](rules/async-watch-latest.md) - Use `watch` for latest-value sharing125- [`async-oneshot-response`](rules/async-oneshot-response.md) - Use `oneshot` for request/response126- [`async-joinset-structured`](rules/async-joinset-structured.md) - Use `JoinSet` for dynamic task groups127- [`async-clone-before-await`](rules/async-clone-before-await.md) - Clone data before await, release locks128129### 6. Compiler Optimization (HIGH)130131- [`opt-inline-small`](rules/opt-inline-small.md) - Use `#[inline]` for small hot functions132- [`opt-inline-always-rare`](rules/opt-inline-always-rare.md) - Use `#[inline(always)]` sparingly133- [`opt-inline-never-cold`](rules/opt-inline-never-cold.md) - Use `#[inline(never)]` for cold paths134- [`opt-cold-unlikely`](rules/opt-cold-unlikely.md) - Use `#[cold]` for error/unlikely paths135- [`opt-likely-hint`](rules/opt-likely-hint.md) - Use `likely()`/`unlikely()` for branch hints136- [`opt-lto-release`](rules/opt-lto-release.md) - Enable LTO in release builds137- [`opt-codegen-units`](rules/opt-codegen-units.md) - Use `codegen-units = 1` for max optimization138- [`opt-pgo-profile`](rules/opt-pgo-profile.md) - Use PGO for production builds139- [`opt-target-cpu`](rules/opt-target-cpu.md) - Set `target-cpu=native` for local builds140- [`opt-bounds-check`](rules/opt-bounds-check.md) - Use iterators to avoid bounds checks141- [`opt-simd-portable`](rules/opt-simd-portable.md) - Use portable SIMD for data-parallel ops142- [`opt-cache-friendly`](rules/opt-cache-friendly.md) - Design cache-friendly data layouts (SoA)143144### 7. Naming Conventions (MEDIUM)145146- [`name-types-camel`](rules/name-types-camel.md) - Use `UpperCamelCase` for types, traits, enums147- [`name-variants-camel`](rules/name-variants-camel.md) - Use `UpperCamelCase` for enum variants148- [`name-funcs-snake`](rules/name-funcs-snake.md) - Use `snake_case` for functions, methods, modules149- [`name-consts-screaming`](rules/name-consts-screaming.md) - Use `SCREAMING_SNAKE_CASE` for constants/statics150- [`name-lifetime-short`](rules/name-lifetime-short.md) - Use short lowercase lifetimes: `'a`, `'de`, `'src`151- [`name-type-param-single`](rules/name-type-param-single.md) - Use single uppercase for type params: `T`, `E`, `K`, `V`152- [`name-as-free`](rules/name-as-free.md) - `as_` prefix: free reference conversion153- [`name-to-expensive`](rules/name-to-expensive.md) - `to_` prefix: expensive conversion154- [`name-into-ownership`](rules/name-into-ownership.md) - `into_` prefix: ownership transfer155- [`name-no-get-prefix`](rules/name-no-get-prefix.md) - No `get_` prefix for simple getters156- [`name-is-has-bool`](rules/name-is-has-bool.md) - Use `is_`, `has_`, `can_` for boolean methods157- [`name-iter-convention`](rules/name-iter-convention.md) - Use `iter`/`iter_mut`/`into_iter` for iterators158- [`name-iter-method`](rules/name-iter-method.md) - Name iterator methods consistently159- [`name-iter-type-match`](rules/name-iter-type-match.md) - Iterator type names match method160- [`name-acronym-word`](rules/name-acronym-word.md) - Treat acronyms as words: `Uuid` not `UUID`161- [`name-crate-no-rs`](rules/name-crate-no-rs.md) - Crate names: no `-rs` suffix162163### 8. Type Safety (MEDIUM)164165- [`type-newtype-ids`](rules/type-newtype-ids.md) - Wrap IDs in newtypes: `UserId(u64)`166- [`type-newtype-validated`](rules/type-newtype-validated.md) - Newtypes for validated data: `Email`, `Url`167- [`type-enum-states`](rules/type-enum-states.md) - Use enums for mutually exclusive states168- [`type-option-nullable`](rules/type-option-nullable.md) - Use `Option<T>` for nullable values169- [`type-result-fallible`](rules/type-result-fallible.md) - Use `Result<T, E>` for fallible operations170- [`type-phantom-marker`](rules/type-phantom-marker.md) - Use `PhantomData<T>` for type-level markers171- [`type-never-diverge`](rules/type-never-diverge.md) - Use `!` type for functions that never return172- [`type-generic-bounds`](rules/type-generic-bounds.md) - Add trait bounds only where needed173- [`type-no-stringly`](rules/type-no-stringly.md) - Avoid stringly-typed APIs, use enums/newtypes174- [`type-repr-transparent`](rules/type-repr-transparent.md) - Use `#[repr(transparent)]` for FFI newtypes175176### 9. Testing (MEDIUM)177178- [`test-cfg-test-module`](rules/test-cfg-test-module.md) - Use `#[cfg(test)] mod tests { }`179- [`test-use-super`](rules/test-use-super.md) - Use `use super::*;` in test modules180- [`test-integration-dir`](rules/test-integration-dir.md) - Put integration tests in `tests/` directory181- [`test-descriptive-names`](rules/test-descriptive-names.md) - Use descriptive test names182- [`test-arrange-act-assert`](rules/test-arrange-act-assert.md) - Structure tests as arrange/act/assert183- [`test-proptest-properties`](rules/test-proptest-properties.md) - Use `proptest` for property-based testing184- [`test-mockall-mocking`](rules/test-mockall-mocking.md) - Use `mockall` for trait mocking185- [`test-mock-traits`](rules/test-mock-traits.md) - Use traits for dependencies to enable mocking186- [`test-fixture-raii`](rules/test-fixture-raii.md) - Use RAII pattern (Drop) for test cleanup187- [`test-tokio-async`](rules/test-tokio-async.md) - Use `#[tokio::test]` for async tests188- [`test-should-panic`](rules/test-should-panic.md) - Use `#[should_panic]` for panic tests189- [`test-criterion-bench`](rules/test-criterion-bench.md) - Use `criterion` for benchmarking190- [`test-doctest-examples`](rules/test-doctest-examples.md) - Keep doc examples as executable tests191192### 10. Documentation (MEDIUM)193194- [`doc-all-public`](rules/doc-all-public.md) - Document all public items with `///`195- [`doc-module-inner`](rules/doc-module-inner.md) - Use `//!` for module-level documentation196- [`doc-examples-section`](rules/doc-examples-section.md) - Include `# Examples` with runnable code197- [`doc-errors-section`](rules/doc-errors-section.md) - Include `# Errors` for fallible functions198- [`doc-panics-section`](rules/doc-panics-section.md) - Include `# Panics` for panicking functions199- [`doc-safety-section`](rules/doc-safety-section.md) - Include `# Safety` for unsafe functions200- [`doc-question-mark`](rules/doc-question-mark.md) - Use `?` in examples, not `.unwrap()`201- [`doc-hidden-setup`](rules/doc-hidden-setup.md) - Use `# ` prefix to hide example setup code202- [`doc-intra-links`](rules/doc-intra-links.md) - Use intra-doc links: `[Vec]`203- [`doc-link-types`](rules/doc-link-types.md) - Link related types and functions in docs204- [`doc-cargo-metadata`](rules/doc-cargo-metadata.md) - Fill `Cargo.toml` metadata205206### 11. Performance Patterns (MEDIUM)207208- [`perf-iter-over-index`](rules/perf-iter-over-index.md) - Prefer iterators over manual indexing209- [`perf-iter-lazy`](rules/perf-iter-lazy.md) - Keep iterators lazy, collect() only when needed210- [`perf-collect-once`](rules/perf-collect-once.md) - Don't `collect()` intermediate iterators211- [`perf-entry-api`](rules/perf-entry-api.md) - Use `entry()` API for map insert-or-update212- [`perf-drain-reuse`](rules/perf-drain-reuse.md) - Use `drain()` to reuse allocations213- [`perf-extend-batch`](rules/perf-extend-batch.md) - Use `extend()` for batch insertions214- [`perf-chain-avoid`](rules/perf-chain-avoid.md) - Avoid `chain()` in hot loops215- [`perf-collect-into`](rules/perf-collect-into.md) - Use `collect_into()` for reusing containers216- [`perf-black-box-bench`](rules/perf-black-box-bench.md) - Use `black_box()` in benchmarks217- [`perf-release-profile`](rules/perf-release-profile.md) - Optimize release profile settings218- [`perf-profile-first`](rules/perf-profile-first.md) - Profile before optimizing219220### 12. Project Structure (LOW)221222- [`proj-lib-main-split`](rules/proj-lib-main-split.md) - Keep `main.rs` minimal, logic in `lib.rs`223- [`proj-mod-by-feature`](rules/proj-mod-by-feature.md) - Organize modules by feature, not type224- [`proj-flat-small`](rules/proj-flat-small.md) - Keep small projects flat225- [`proj-mod-rs-dir`](rules/proj-mod-rs-dir.md) - Use `mod.rs` for multi-file modules226- [`proj-pub-crate-internal`](rules/proj-pub-crate-internal.md) - Use `pub(crate)` for internal APIs227- [`proj-pub-super-parent`](rules/proj-pub-super-parent.md) - Use `pub(super)` for parent-only visibility228- [`proj-pub-use-reexport`](rules/proj-pub-use-reexport.md) - Use `pub use` for clean public API229- [`proj-prelude-module`](rules/proj-prelude-module.md) - Create `prelude` module for common imports230- [`proj-bin-dir`](rules/proj-bin-dir.md) - Put multiple binaries in `src/bin/`231- [`proj-workspace-large`](rules/proj-workspace-large.md) - Use workspaces for large projects232- [`proj-workspace-deps`](rules/proj-workspace-deps.md) - Use workspace dependency inheritance233234### 13. Clippy & Linting (LOW)235236- [`lint-deny-correctness`](rules/lint-deny-correctness.md) - `#![deny(clippy::correctness)]`237- [`lint-warn-suspicious`](rules/lint-warn-suspicious.md) - `#![warn(clippy::suspicious)]`238- [`lint-warn-style`](rules/lint-warn-style.md) - `#![warn(clippy::style)]`239- [`lint-warn-complexity`](rules/lint-warn-complexity.md) - `#![warn(clippy::complexity)]`240- [`lint-warn-perf`](rules/lint-warn-perf.md) - `#![warn(clippy::perf)]`241- [`lint-pedantic-selective`](rules/lint-pedantic-selective.md) - Enable `clippy::pedantic` selectively242- [`lint-missing-docs`](rules/lint-missing-docs.md) - `#![warn(missing_docs)]`243- [`lint-unsafe-doc`](rules/lint-unsafe-doc.md) - `#![warn(clippy::undocumented_unsafe_blocks)]`244- [`lint-cargo-metadata`](rules/lint-cargo-metadata.md) - `#![warn(clippy::cargo)]` for published crates245- [`lint-rustfmt-check`](rules/lint-rustfmt-check.md) - Run `cargo fmt --check` in CI246- [`lint-workspace-lints`](rules/lint-workspace-lints.md) - Configure lints at workspace level247248### 14. Anti-patterns (REFERENCE)249250- [`anti-unwrap-abuse`](rules/anti-unwrap-abuse.md) - Don't use `.unwrap()` in production code251- [`anti-expect-lazy`](rules/anti-expect-lazy.md) - Don't use `.expect()` for recoverable errors252- [`anti-clone-excessive`](rules/anti-clone-excessive.md) - Don't clone when borrowing works253- [`anti-lock-across-await`](rules/anti-lock-across-await.md) - Don't hold locks across `.await`254- [`anti-string-for-str`](rules/anti-string-for-str.md) - Don't accept `&String` when `&str` works255- [`anti-vec-for-slice`](rules/anti-vec-for-slice.md) - Don't accept `&Vec<T>` when `&[T]` works256- [`anti-index-over-iter`](rules/anti-index-over-iter.md) - Don't use indexing when iterators work257- [`anti-panic-expected`](rules/anti-panic-expected.md) - Don't panic on expected/recoverable errors258- [`anti-empty-catch`](rules/anti-empty-catch.md) - Don't use empty `if let Err(_) = ...` blocks259- [`anti-over-abstraction`](rules/anti-over-abstraction.md) - Don't over-abstract with excessive generics260- [`anti-premature-optimize`](rules/anti-premature-optimize.md) - Don't optimize before profiling261- [`anti-type-erasure`](rules/anti-type-erasure.md) - Don't use `Box<dyn Trait>` when `impl Trait` works262- [`anti-format-hot-path`](rules/anti-format-hot-path.md) - Don't use `format!()` in hot paths263- [`anti-collect-intermediate`](rules/anti-collect-intermediate.md) - Don't `collect()` intermediate iterators264- [`anti-stringly-typed`](rules/anti-stringly-typed.md) - Don't use strings for structured data265266---267268## Recommended Cargo.toml Settings269270### Standalone project271272```toml273[profile.release]274opt-level = 3275lto = "fat"276codegen-units = 1277panic = "abort"278strip = true279280[profile.bench]281inherits = "release"282debug = true283strip = false284285[profile.dev]286opt-level = 0287debug = true288289[profile.dev.package."*"]290opt-level = 3 # Optimize dependencies in dev291```292293### Workspace294295```toml296[workspace]297members = ["crates/*"]298resolver = "2"299300[workspace.package]301edition = "2024"302rust-version = "1.85"303license = "MIT"304305[workspace.dependencies]306# Pin shared dependencies here307tokio = { version = "1", features = ["full"] }308serde = { version = "1", features = ["derive"] }309thiserror = "2"310anyhow = "1"311312[workspace.lints.rust]313unsafe_code = "forbid"314315[workspace.lints.clippy]316correctness = { level = "deny", priority = -1 }317suspicious = { level = "warn", priority = -1 }318style = { level = "warn", priority = -1 }319complexity = { level = "warn", priority = -1 }320perf = { level = "warn", priority = -1 }321pedantic = { level = "warn", priority = -1 }322323[profile.release]324opt-level = 3325lto = "fat"326codegen-units = 1327panic = "abort"328strip = true329330[profile.bench]331inherits = "release"332debug = true333strip = false334335[profile.dev]336opt-level = 0337debug = true338339[profile.dev.package."*"]340opt-level = 3 # Optimize dependencies in dev341```342343Member crates inherit from the workspace:344345```toml346[package]347name = "my-crate"348version = "0.1.0"349edition.workspace = true350rust-version.workspace = true351license.workspace = true352353[dependencies]354tokio = { workspace = true }355serde = { workspace = true }356357[lints]358workspace = true359```360361---362363## How to Use364365This skill provides rule identifiers for quick reference. When generating or reviewing Rust code:3663671. **Check relevant category** based on task type3682. **Apply rules** with matching prefix3693. **Prioritize** CRITICAL > HIGH > MEDIUM > LOW3704. **Read rule files** in `rules/` for detailed examples371372### Rule Application by Task373374| Task | Primary Categories |375|------|-------------------|376| New function | `own-`, `err-`, `name-` |377| New struct/API | `api-`, `type-`, `doc-` |378| Async code | `async-`, `own-` |379| Error handling | `err-`, `api-` |380| Memory optimization | `mem-`, `own-`, `perf-` |381| Performance tuning | `opt-`, `mem-`, `perf-` |382| Code review | `anti-`, `lint-` |383384---385386## Sources387388This skill synthesizes best practices from:389- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)390- [Rust Performance Book](https://nnethercote.github.io/perf-book/)391- [Rust Design Patterns](https://rust-unofficial.github.io/patterns/)392- Production codebases: ripgrep, tokio, serde, polars, axum, deno393- Clippy lint documentation394- Community conventions (2024-2025)