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
[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
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:1415- Writing new Rust functions, structs, or modules16- Implementing error handling or async code17- Designing public APIs for libraries18- Reviewing code for ownership/borrowing issues19- Optimizing memory usage or reducing allocations20- Tuning performance for hot paths21- Refactoring existing Rust code2223## Rule Categories by Priority2425| Priority | Category | Impact | Prefix | Rules |26| -------- | --------------------- | --------- | -------- | ----- |27| 1 | Ownership & Borrowing | CRITICAL | `own-` | 12 |28| 2 | Error Handling | CRITICAL | `err-` | 12 |29| 3 | Memory Optimization | CRITICAL | `mem-` | 15 |30| 4 | API Design | HIGH | `api-` | 15 |31| 5 | Async/Await | HIGH | `async-` | 15 |32| 6 | Compiler Optimization | HIGH | `opt-` | 12 |33| 7 | Naming Conventions | MEDIUM | `name-` | 16 |34| 8 | Type Safety | MEDIUM | `type-` | 10 |35| 9 | Testing | MEDIUM | `test-` | 13 |36| 10 | Documentation | MEDIUM | `doc-` | 11 |37| 11 | Performance Patterns | MEDIUM | `perf-` | 11 |38| 12 | Project Structure | LOW | `proj-` | 11 |39| 13 | Clippy & Linting | LOW | `lint-` | 11 |40| 14 | Anti-patterns | REFERENCE | `anti-` | 15 |4142---4344## Quick Reference4546### 1. Ownership & Borrowing (CRITICAL)4748- [`own-borrow-over-clone`](rules/own-borrow-over-clone.md) - Prefer `&T` borrowing over `.clone()`49- [`own-slice-over-vec`](rules/own-slice-over-vec.md) - Accept `&[T]` not `&Vec<T>`, `&str` not `&String`50- [`own-cow-conditional`](rules/own-cow-conditional.md) - Use `Cow<'a, T>` for conditional ownership51- [`own-arc-shared`](rules/own-arc-shared.md) - Use `Arc<T>` for thread-safe shared ownership52- [`own-rc-single-thread`](rules/own-rc-single-thread.md) - Use `Rc<T>` for single-threaded sharing53- [`own-refcell-interior`](rules/own-refcell-interior.md) - Use `RefCell<T>` for interior mutability (single-thread)54- [`own-mutex-interior`](rules/own-mutex-interior.md) - Use `Mutex<T>` for interior mutability (multi-thread)55- [`own-rwlock-readers`](rules/own-rwlock-readers.md) - Use `RwLock<T>` when reads dominate writes56- [`own-copy-small`](rules/own-copy-small.md) - Derive `Copy` for small, trivial types57- [`own-clone-explicit`](rules/own-clone-explicit.md) - Make `Clone` explicit, avoid implicit copies58- [`own-move-large`](rules/own-move-large.md) - Move large data instead of cloning59- [`own-lifetime-elision`](rules/own-lifetime-elision.md) - Rely on lifetime elision when possible6061### 2. Error Handling (CRITICAL)6263- [`err-thiserror-lib`](rules/err-thiserror-lib.md) - Use `thiserror` for library error types64- [`err-anyhow-app`](rules/err-anyhow-app.md) - Use `anyhow` for application error handling65- [`err-result-over-panic`](rules/err-result-over-panic.md) - Return `Result`, don't panic on expected errors66- [`err-context-chain`](rules/err-context-chain.md) - Add context with `.context()` or `.with_context()`67- [`err-no-unwrap-prod`](rules/err-no-unwrap-prod.md) - Never use `.unwrap()` in production code68- [`err-expect-bugs-only`](rules/err-expect-bugs-only.md) - Use `.expect()` only for programming errors69- [`err-question-mark`](rules/err-question-mark.md) - Use `?` operator for clean propagation70- [`err-from-impl`](rules/err-from-impl.md) - Use `#[from]` for automatic error conversion71- [`err-source-chain`](rules/err-source-chain.md) - Use `#[source]` to chain underlying errors72- [`err-lowercase-msg`](rules/err-lowercase-msg.md) - Error messages: lowercase, no trailing punctuation73- [`err-doc-errors`](rules/err-doc-errors.md) - Document errors with `# Errors` section74- [`err-custom-type`](rules/err-custom-type.md) - Create custom error types, not `Box<dyn Error>`7576### 3. Memory Optimization (CRITICAL)7778- [`mem-with-capacity`](rules/mem-with-capacity.md) - Use `with_capacity()` when size is known79- [`mem-smallvec`](rules/mem-smallvec.md) - Use `SmallVec` for usually-small collections80- [`mem-arrayvec`](rules/mem-arrayvec.md) - Use `ArrayVec` for bounded-size collections81- [`mem-box-large-variant`](rules/mem-box-large-variant.md) - Box large enum variants to reduce type size82- [`mem-boxed-slice`](rules/mem-boxed-slice.md) - Use `Box<[T]>` instead of `Vec<T>` when fixed83- [`mem-thinvec`](rules/mem-thinvec.md) - Use `ThinVec` for often-empty vectors84- [`mem-clone-from`](rules/mem-clone-from.md) - Use `clone_from()` to reuse allocations85- [`mem-reuse-collections`](rules/mem-reuse-collections.md) - Reuse collections with `clear()` in loops86- [`mem-avoid-format`](rules/mem-avoid-format.md) - Avoid `format!()` when string literals work87- [`mem-write-over-format`](rules/mem-write-over-format.md) - Use `write!()` instead of `format!()`88- [`mem-arena-allocator`](rules/mem-arena-allocator.md) - Use arena allocators for batch allocations89- [`mem-zero-copy`](rules/mem-zero-copy.md) - Use zero-copy patterns with slices and `Bytes`90- [`mem-compact-string`](rules/mem-compact-string.md) - Use `CompactString` for small string optimization91- [`mem-smaller-integers`](rules/mem-smaller-integers.md) - Use smallest integer type that fits92- [`mem-assert-type-size`](rules/mem-assert-type-size.md) - Assert hot type sizes to prevent regressions9394### 4. API Design (HIGH)9596- [`api-builder-pattern`](rules/api-builder-pattern.md) - Use Builder pattern for complex construction97- [`api-builder-must-use`](rules/api-builder-must-use.md) - Add `#[must_use]` to builder types98- [`api-newtype-safety`](rules/api-newtype-safety.md) - Use newtypes for type-safe distinctions99- [`api-typestate`](rules/api-typestate.md) - Use typestate for compile-time state machines100- [`api-sealed-trait`](rules/api-sealed-trait.md) - Seal traits to prevent external implementations101- [`api-extension-trait`](rules/api-extension-trait.md) - Use extension traits to add methods to foreign types102- [`api-parse-dont-validate`](rules/api-parse-dont-validate.md) - Parse into validated types at boundaries103- [`api-impl-into`](rules/api-impl-into.md) - Accept `impl Into<T>` for flexible string inputs104- [`api-impl-asref`](rules/api-impl-asref.md) - Accept `impl AsRef<T>` for borrowed inputs105- [`api-must-use`](rules/api-must-use.md) - Add `#[must_use]` to `Result` returning functions106- [`api-non-exhaustive`](rules/api-non-exhaustive.md) - Use `#[non_exhaustive]` for future-proof enums/structs107- [`api-from-not-into`](rules/api-from-not-into.md) - Implement `From`, not `Into` (auto-derived)108- [`api-default-impl`](rules/api-default-impl.md) - Implement `Default` for sensible defaults109- [`api-common-traits`](rules/api-common-traits.md) - Implement `Debug`, `Clone`, `PartialEq` eagerly110- [`api-serde-optional`](rules/api-serde-optional.md) - Gate `Serialize`/`Deserialize` behind feature flag111112### 5. Async/Await (HIGH)113114- [`async-tokio-runtime`](rules/async-tokio-runtime.md) - Use Tokio for production async runtime115- [`async-no-lock-await`](rules/async-no-lock-await.md) - Never hold `Mutex`/`RwLock` across `.await`116- [`async-spawn-blocking`](rules/async-spawn-blocking.md) - Use `spawn_blocking` for CPU-intensive work117- [`async-tokio-fs`](rules/async-tokio-fs.md) - Use `tokio::fs` not `std::fs` in async code118- [`async-cancellation-token`](rules/async-cancellation-token.md) - Use `CancellationToken` for graceful shutdown119- [`async-join-parallel`](rules/async-join-parallel.md) - Use `tokio::join!` for parallel operations120- [`async-try-join`](rules/async-try-join.md) - Use `tokio::try_join!` for fallible parallel ops121- [`async-select-racing`](rules/async-select-racing.md) - Use `tokio::select!` for racing/timeouts122- [`async-bounded-channel`](rules/async-bounded-channel.md) - Use bounded channels for backpressure123- [`async-mpsc-queue`](rules/async-mpsc-queue.md) - Use `mpsc` for work queues124- [`async-broadcast-pubsub`](rules/async-broadcast-pubsub.md) - Use `broadcast` for pub/sub patterns125- [`async-watch-latest`](rules/async-watch-latest.md) - Use `watch` for latest-value sharing126- [`async-oneshot-response`](rules/async-oneshot-response.md) - Use `oneshot` for request/response127- [`async-joinset-structured`](rules/async-joinset-structured.md) - Use `JoinSet` for dynamic task groups128- [`async-clone-before-await`](rules/async-clone-before-await.md) - Clone data before await, release locks129130### 6. Compiler Optimization (HIGH)131132- [`opt-inline-small`](rules/opt-inline-small.md) - Use `#[inline]` for small hot functions133- [`opt-inline-always-rare`](rules/opt-inline-always-rare.md) - Use `#[inline(always)]` sparingly134- [`opt-inline-never-cold`](rules/opt-inline-never-cold.md) - Use `#[inline(never)]` for cold paths135- [`opt-cold-unlikely`](rules/opt-cold-unlikely.md) - Use `#[cold]` for error/unlikely paths136- [`opt-likely-hint`](rules/opt-likely-hint.md) - Use `likely()`/`unlikely()` for branch hints137- [`opt-lto-release`](rules/opt-lto-release.md) - Enable LTO in release builds138- [`opt-codegen-units`](rules/opt-codegen-units.md) - Use `codegen-units = 1` for max optimization139- [`opt-pgo-profile`](rules/opt-pgo-profile.md) - Use PGO for production builds140- [`opt-target-cpu`](rules/opt-target-cpu.md) - Set `target-cpu=native` for local builds141- [`opt-bounds-check`](rules/opt-bounds-check.md) - Use iterators to avoid bounds checks142- [`opt-simd-portable`](rules/opt-simd-portable.md) - Use portable SIMD for data-parallel ops143- [`opt-cache-friendly`](rules/opt-cache-friendly.md) - Design cache-friendly data layouts (SoA)144145### 7. Naming Conventions (MEDIUM)146147- [`name-types-camel`](rules/name-types-camel.md) - Use `UpperCamelCase` for types, traits, enums148- [`name-variants-camel`](rules/name-variants-camel.md) - Use `UpperCamelCase` for enum variants149- [`name-funcs-snake`](rules/name-funcs-snake.md) - Use `snake_case` for functions, methods, modules150- [`name-consts-screaming`](rules/name-consts-screaming.md) - Use `SCREAMING_SNAKE_CASE` for constants/statics151- [`name-lifetime-short`](rules/name-lifetime-short.md) - Use short lowercase lifetimes: `'a`, `'de`, `'src`152- [`name-type-param-single`](rules/name-type-param-single.md) - Use single uppercase for type params: `T`, `E`, `K`, `V`153- [`name-as-free`](rules/name-as-free.md) - `as_` prefix: free reference conversion154- [`name-to-expensive`](rules/name-to-expensive.md) - `to_` prefix: expensive conversion155- [`name-into-ownership`](rules/name-into-ownership.md) - `into_` prefix: ownership transfer156- [`name-no-get-prefix`](rules/name-no-get-prefix.md) - No `get_` prefix for simple getters157- [`name-is-has-bool`](rules/name-is-has-bool.md) - Use `is_`, `has_`, `can_` for boolean methods158- [`name-iter-convention`](rules/name-iter-convention.md) - Use `iter`/`iter_mut`/`into_iter` for iterators159- [`name-iter-method`](rules/name-iter-method.md) - Name iterator methods consistently160- [`name-iter-type-match`](rules/name-iter-type-match.md) - Iterator type names match method161- [`name-acronym-word`](rules/name-acronym-word.md) - Treat acronyms as words: `Uuid` not `UUID`162- [`name-crate-no-rs`](rules/name-crate-no-rs.md) - Crate names: no `-rs` suffix163164### 8. Type Safety (MEDIUM)165166- [`type-newtype-ids`](rules/type-newtype-ids.md) - Wrap IDs in newtypes: `UserId(u64)`167- [`type-newtype-validated`](rules/type-newtype-validated.md) - Newtypes for validated data: `Email`, `Url`168- [`type-enum-states`](rules/type-enum-states.md) - Use enums for mutually exclusive states169- [`type-option-nullable`](rules/type-option-nullable.md) - Use `Option<T>` for nullable values170- [`type-result-fallible`](rules/type-result-fallible.md) - Use `Result<T, E>` for fallible operations171- [`type-phantom-marker`](rules/type-phantom-marker.md) - Use `PhantomData<T>` for type-level markers172- [`type-never-diverge`](rules/type-never-diverge.md) - Use `!` type for functions that never return173- [`type-generic-bounds`](rules/type-generic-bounds.md) - Add trait bounds only where needed174- [`type-no-stringly`](rules/type-no-stringly.md) - Avoid stringly-typed APIs, use enums/newtypes175- [`type-repr-transparent`](rules/type-repr-transparent.md) - Use `#[repr(transparent)]` for FFI newtypes176177### 9. Testing (MEDIUM)178179- [`test-cfg-test-module`](rules/test-cfg-test-module.md) - Use `#[cfg(test)] mod tests { }`180- [`test-use-super`](rules/test-use-super.md) - Use `use super::*;` in test modules181- [`test-integration-dir`](rules/test-integration-dir.md) - Put integration tests in `tests/` directory182- [`test-descriptive-names`](rules/test-descriptive-names.md) - Use descriptive test names183- [`test-arrange-act-assert`](rules/test-arrange-act-assert.md) - Structure tests as arrange/act/assert184- [`test-proptest-properties`](rules/test-proptest-properties.md) - Use `proptest` for property-based testing185- [`test-mockall-mocking`](rules/test-mockall-mocking.md) - Use `mockall` for trait mocking186- [`test-mock-traits`](rules/test-mock-traits.md) - Use traits for dependencies to enable mocking187- [`test-fixture-raii`](rules/test-fixture-raii.md) - Use RAII pattern (Drop) for test cleanup188- [`test-tokio-async`](rules/test-tokio-async.md) - Use `#[tokio::test]` for async tests189- [`test-should-panic`](rules/test-should-panic.md) - Use `#[should_panic]` for panic tests190- [`test-criterion-bench`](rules/test-criterion-bench.md) - Use `criterion` for benchmarking191- [`test-doctest-examples`](rules/test-doctest-examples.md) - Keep doc examples as executable tests192193### 10. Documentation (MEDIUM)194195- [`doc-all-public`](rules/doc-all-public.md) - Document all public items with `///`196- [`doc-module-inner`](rules/doc-module-inner.md) - Use `//!` for module-level documentation197- [`doc-examples-section`](rules/doc-examples-section.md) - Include `# Examples` with runnable code198- [`doc-errors-section`](rules/doc-errors-section.md) - Include `# Errors` for fallible functions199- [`doc-panics-section`](rules/doc-panics-section.md) - Include `# Panics` for panicking functions200- [`doc-safety-section`](rules/doc-safety-section.md) - Include `# Safety` for unsafe functions201- [`doc-question-mark`](rules/doc-question-mark.md) - Use `?` in examples, not `.unwrap()`202- [`doc-hidden-setup`](rules/doc-hidden-setup.md) - Use `# ` prefix to hide example setup code203- [`doc-intra-links`](rules/doc-intra-links.md) - Use intra-doc links: `[Vec]`204- [`doc-link-types`](rules/doc-link-types.md) - Link related types and functions in docs205- [`doc-cargo-metadata`](rules/doc-cargo-metadata.md) - Fill `Cargo.toml` metadata206207### 11. Performance Patterns (MEDIUM)208209- [`perf-iter-over-index`](rules/perf-iter-over-index.md) - Prefer iterators over manual indexing210- [`perf-iter-lazy`](rules/perf-iter-lazy.md) - Keep iterators lazy, collect() only when needed211- [`perf-collect-once`](rules/perf-collect-once.md) - Don't `collect()` intermediate iterators212- [`perf-entry-api`](rules/perf-entry-api.md) - Use `entry()` API for map insert-or-update213- [`perf-drain-reuse`](rules/perf-drain-reuse.md) - Use `drain()` to reuse allocations214- [`perf-extend-batch`](rules/perf-extend-batch.md) - Use `extend()` for batch insertions215- [`perf-chain-avoid`](rules/perf-chain-avoid.md) - Avoid `chain()` in hot loops216- [`perf-collect-into`](rules/perf-collect-into.md) - Use `collect_into()` for reusing containers217- [`perf-black-box-bench`](rules/perf-black-box-bench.md) - Use `black_box()` in benchmarks218- [`perf-release-profile`](rules/perf-release-profile.md) - Optimize release profile settings219- [`perf-profile-first`](rules/perf-profile-first.md) - Profile before optimizing220221### 12. Project Structure (LOW)222223- [`proj-lib-main-split`](rules/proj-lib-main-split.md) - Keep `main.rs` minimal, logic in `lib.rs`224- [`proj-mod-by-feature`](rules/proj-mod-by-feature.md) - Organize modules by feature, not type225- [`proj-flat-small`](rules/proj-flat-small.md) - Keep small projects flat226- [`proj-mod-rs-dir`](rules/proj-mod-rs-dir.md) - Use `mod.rs` for multi-file modules227- [`proj-pub-crate-internal`](rules/proj-pub-crate-internal.md) - Use `pub(crate)` for internal APIs228- [`proj-pub-super-parent`](rules/proj-pub-super-parent.md) - Use `pub(super)` for parent-only visibility229- [`proj-pub-use-reexport`](rules/proj-pub-use-reexport.md) - Use `pub use` for clean public API230- [`proj-prelude-module`](rules/proj-prelude-module.md) - Create `prelude` module for common imports231- [`proj-bin-dir`](rules/proj-bin-dir.md) - Put multiple binaries in `src/bin/`232- [`proj-workspace-large`](rules/proj-workspace-large.md) - Use workspaces for large projects233- [`proj-workspace-deps`](rules/proj-workspace-deps.md) - Use workspace dependency inheritance234235### 13. Clippy & Linting (LOW)236237- [`lint-deny-correctness`](rules/lint-deny-correctness.md) - `#![deny(clippy::correctness)]`238- [`lint-warn-suspicious`](rules/lint-warn-suspicious.md) - `#![warn(clippy::suspicious)]`239- [`lint-warn-style`](rules/lint-warn-style.md) - `#![warn(clippy::style)]`240- [`lint-warn-complexity`](rules/lint-warn-complexity.md) - `#![warn(clippy::complexity)]`241- [`lint-warn-perf`](rules/lint-warn-perf.md) - `#![warn(clippy::perf)]`242- [`lint-pedantic-selective`](rules/lint-pedantic-selective.md) - Enable `clippy::pedantic` selectively243- [`lint-missing-docs`](rules/lint-missing-docs.md) - `#![warn(missing_docs)]`244- [`lint-unsafe-doc`](rules/lint-unsafe-doc.md) - `#![warn(clippy::undocumented_unsafe_blocks)]`245- [`lint-cargo-metadata`](rules/lint-cargo-metadata.md) - `#![warn(clippy::cargo)]` for published crates246- [`lint-rustfmt-check`](rules/lint-rustfmt-check.md) - Run `cargo fmt --check` in CI247- [`lint-workspace-lints`](rules/lint-workspace-lints.md) - Configure lints at workspace level248249### 14. Anti-patterns (REFERENCE)250251- [`anti-unwrap-abuse`](rules/anti-unwrap-abuse.md) - Don't use `.unwrap()` in production code252- [`anti-expect-lazy`](rules/anti-expect-lazy.md) - Don't use `.expect()` for recoverable errors253- [`anti-clone-excessive`](rules/anti-clone-excessive.md) - Don't clone when borrowing works254- [`anti-lock-across-await`](rules/anti-lock-across-await.md) - Don't hold locks across `.await`255- [`anti-string-for-str`](rules/anti-string-for-str.md) - Don't accept `&String` when `&str` works256- [`anti-vec-for-slice`](rules/anti-vec-for-slice.md) - Don't accept `&Vec<T>` when `&[T]` works257- [`anti-index-over-iter`](rules/anti-index-over-iter.md) - Don't use indexing when iterators work258- [`anti-panic-expected`](rules/anti-panic-expected.md) - Don't panic on expected/recoverable errors259- [`anti-empty-catch`](rules/anti-empty-catch.md) - Don't use empty `if let Err(_) = ...` blocks260- [`anti-over-abstraction`](rules/anti-over-abstraction.md) - Don't over-abstract with excessive generics261- [`anti-premature-optimize`](rules/anti-premature-optimize.md) - Don't optimize before profiling262- [`anti-type-erasure`](rules/anti-type-erasure.md) - Don't use `Box<dyn Trait>` when `impl Trait` works263- [`anti-format-hot-path`](rules/anti-format-hot-path.md) - Don't use `format!()` in hot paths264- [`anti-collect-intermediate`](rules/anti-collect-intermediate.md) - Don't `collect()` intermediate iterators265- [`anti-stringly-typed`](rules/anti-stringly-typed.md) - Don't use strings for structured data266267---268269## Recommended Cargo.toml Settings270271```toml272[profile.release]273opt-level = 3274lto = "fat"275codegen-units = 1276panic = "abort"277strip = true278279[profile.bench]280inherits = "release"281debug = true282strip = false283284[profile.dev]285opt-level = 0286debug = true287288[profile.dev.package."*"]289opt-level = 3 # Optimize dependencies in dev290```291292---293294## How to Use295296This skill provides rule identifiers for quick reference. When generating or reviewing Rust code:2972981. **Check relevant category** based on task type2992. **Apply rules** with matching prefix3003. **Prioritize** CRITICAL > HIGH > MEDIUM > LOW3014. **Read rule files** in `rules/` for detailed examples302303### Rule Application by Task304305| Task | Primary Categories |306| ------------------- | ----------------------- |307| New function | `own-`, `err-`, `name-` |308| New struct/API | `api-`, `type-`, `doc-` |309| Async code | `async-`, `own-` |310| Error handling | `err-`, `api-` |311| Memory optimization | `mem-`, `own-`, `perf-` |312| Performance tuning | `opt-`, `mem-`, `perf-` |313| Code review | `anti-`, `lint-` |314315---316317## Sources318319This skill synthesizes best practices from:320321- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)322- [Rust Performance Book](https://nnethercote.github.io/perf-book/)323- [Rust Design Patterns](https://rust-unofficial.github.io/patterns/)324- Production codebases: ripgrep, tokio, serde, polars, axum, deno325- Clippy lint documentation326- Community conventions (2024-2025)