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---6
7# Rust Best Practices
8
9Comprehensive 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.
10
11## When to Apply
12
13Reference these guidelines when:
14- Writing new Rust functions, structs, or modules
15- Implementing error handling or async code
16- Designing public APIs for libraries
17- Reviewing code for ownership/borrowing issues
18- Optimizing memory usage or reducing allocations
19- Tuning performance for hot paths
20- Refactoring existing Rust code
21
22## Rule Categories by Priority
23
24| 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 |
40
41---
42
43## Quick Reference
44
45### 1. Ownership & Borrowing (CRITICAL)
46
47- [`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 ownership
50- [`own-arc-shared`](rules/own-arc-shared.md) - Use `Arc<T>` for thread-safe shared ownership
51- [`own-rc-single-thread`](rules/own-rc-single-thread.md) - Use `Rc<T>` for single-threaded sharing
52- [`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 writes
55- [`own-copy-small`](rules/own-copy-small.md) - Derive `Copy` for small, trivial types
56- [`own-clone-explicit`](rules/own-clone-explicit.md) - Make `Clone` explicit, avoid implicit copies
57- [`own-move-large`](rules/own-move-large.md) - Move large data instead of cloning
58- [`own-lifetime-elision`](rules/own-lifetime-elision.md) - Rely on lifetime elision when possible
59
60### 2. Error Handling (CRITICAL)
61
62- [`err-thiserror-lib`](rules/err-thiserror-lib.md) - Use `thiserror` for library error types
63- [`err-anyhow-app`](rules/err-anyhow-app.md) - Use `anyhow` for application error handling
64- [`err-result-over-panic`](rules/err-result-over-panic.md) - Return `Result`, don't panic on expected errors
65- [`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 code
67- [`err-expect-bugs-only`](rules/err-expect-bugs-only.md) - Use `.expect()` only for programming errors
68- [`err-question-mark`](rules/err-question-mark.md) - Use `?` operator for clean propagation
69- [`err-from-impl`](rules/err-from-impl.md) - Use `#[from]` for automatic error conversion
70- [`err-source-chain`](rules/err-source-chain.md) - Use `#[source]` to chain underlying errors
71- [`err-lowercase-msg`](rules/err-lowercase-msg.md) - Error messages: lowercase, no trailing punctuation
72- [`err-doc-errors`](rules/err-doc-errors.md) - Document errors with `# Errors` section
73- [`err-custom-type`](rules/err-custom-type.md) - Create custom error types, not `Box<dyn Error>`
74
75### 3. Memory Optimization (CRITICAL)
76
77- [`mem-with-capacity`](rules/mem-with-capacity.md) - Use `with_capacity()` when size is known
78- [`mem-smallvec`](rules/mem-smallvec.md) - Use `SmallVec` for usually-small collections
79- [`mem-arrayvec`](rules/mem-arrayvec.md) - Use `ArrayVec` for bounded-size collections
80- [`mem-box-large-variant`](rules/mem-box-large-variant.md) - Box large enum variants to reduce type size
81- [`mem-boxed-slice`](rules/mem-boxed-slice.md) - Use `Box<[T]>` instead of `Vec<T>` when fixed
82- [`mem-thinvec`](rules/mem-thinvec.md) - Use `ThinVec` for often-empty vectors
83- [`mem-clone-from`](rules/mem-clone-from.md) - Use `clone_from()` to reuse allocations
84- [`mem-reuse-collections`](rules/mem-reuse-collections.md) - Reuse collections with `clear()` in loops
85- [`mem-avoid-format`](rules/mem-avoid-format.md) - Avoid `format!()` when string literals work
86- [`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 allocations
88- [`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 optimization
90- [`mem-smaller-integers`](rules/mem-smaller-integers.md) - Use smallest integer type that fits
91- [`mem-assert-type-size`](rules/mem-assert-type-size.md) - Assert hot type sizes to prevent regressions
92
93### 4. API Design (HIGH)
94
95- [`api-builder-pattern`](rules/api-builder-pattern.md) - Use Builder pattern for complex construction
96- [`api-builder-must-use`](rules/api-builder-must-use.md) - Add `#[must_use]` to builder types
97- [`api-newtype-safety`](rules/api-newtype-safety.md) - Use newtypes for type-safe distinctions
98- [`api-typestate`](rules/api-typestate.md) - Use typestate for compile-time state machines
99- [`api-sealed-trait`](rules/api-sealed-trait.md) - Seal traits to prevent external implementations
100- [`api-extension-trait`](rules/api-extension-trait.md) - Use extension traits to add methods to foreign types
101- [`api-parse-dont-validate`](rules/api-parse-dont-validate.md) - Parse into validated types at boundaries
102- [`api-impl-into`](rules/api-impl-into.md) - Accept `impl Into<T>` for flexible string inputs
103- [`api-impl-asref`](rules/api-impl-asref.md) - Accept `impl AsRef<T>` for borrowed inputs
104- [`api-must-use`](rules/api-must-use.md) - Add `#[must_use]` to `Result` returning functions
105- [`api-non-exhaustive`](rules/api-non-exhaustive.md) - Use `#[non_exhaustive]` for future-proof enums/structs
106- [`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 defaults
108- [`api-common-traits`](rules/api-common-traits.md) - Implement `Debug`, `Clone`, `PartialEq` eagerly
109- [`api-serde-optional`](rules/api-serde-optional.md) - Gate `Serialize`/`Deserialize` behind feature flag
110
111### 5. Async/Await (HIGH)
112
113- [`async-tokio-runtime`](rules/async-tokio-runtime.md) - Use Tokio for production async runtime
114- [`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 work
116- [`async-tokio-fs`](rules/async-tokio-fs.md) - Use `tokio::fs` not `std::fs` in async code
117- [`async-cancellation-token`](rules/async-cancellation-token.md) - Use `CancellationToken` for graceful shutdown
118- [`async-join-parallel`](rules/async-join-parallel.md) - Use `tokio::join!` for parallel operations
119- [`async-try-join`](rules/async-try-join.md) - Use `tokio::try_join!` for fallible parallel ops
120- [`async-select-racing`](rules/async-select-racing.md) - Use `tokio::select!` for racing/timeouts
121- [`async-bounded-channel`](rules/async-bounded-channel.md) - Use bounded channels for backpressure
122- [`async-mpsc-queue`](rules/async-mpsc-queue.md) - Use `mpsc` for work queues
123- [`async-broadcast-pubsub`](rules/async-broadcast-pubsub.md) - Use `broadcast` for pub/sub patterns
124- [`async-watch-latest`](rules/async-watch-latest.md) - Use `watch` for latest-value sharing
125- [`async-oneshot-response`](rules/async-oneshot-response.md) - Use `oneshot` for request/response
126- [`async-joinset-structured`](rules/async-joinset-structured.md) - Use `JoinSet` for dynamic task groups
127- [`async-clone-before-await`](rules/async-clone-before-await.md) - Clone data before await, release locks
128
129### 6. Compiler Optimization (HIGH)
130
131- [`opt-inline-small`](rules/opt-inline-small.md) - Use `#[inline]` for small hot functions
132- [`opt-inline-always-rare`](rules/opt-inline-always-rare.md) - Use `#[inline(always)]` sparingly
133- [`opt-inline-never-cold`](rules/opt-inline-never-cold.md) - Use `#[inline(never)]` for cold paths
134- [`opt-cold-unlikely`](rules/opt-cold-unlikely.md) - Use `#[cold]` for error/unlikely paths
135- [`opt-likely-hint`](rules/opt-likely-hint.md) - Use `likely()`/`unlikely()` for branch hints
136- [`opt-lto-release`](rules/opt-lto-release.md) - Enable LTO in release builds
137- [`opt-codegen-units`](rules/opt-codegen-units.md) - Use `codegen-units = 1` for max optimization
138- [`opt-pgo-profile`](rules/opt-pgo-profile.md) - Use PGO for production builds
139- [`opt-target-cpu`](rules/opt-target-cpu.md) - Set `target-cpu=native` for local builds
140- [`opt-bounds-check`](rules/opt-bounds-check.md) - Use iterators to avoid bounds checks
141- [`opt-simd-portable`](rules/opt-simd-portable.md) - Use portable SIMD for data-parallel ops
142- [`opt-cache-friendly`](rules/opt-cache-friendly.md) - Design cache-friendly data layouts (SoA)
143
144### 7. Naming Conventions (MEDIUM)
145
146- [`name-types-camel`](rules/name-types-camel.md) - Use `UpperCamelCase` for types, traits, enums
147- [`name-variants-camel`](rules/name-variants-camel.md) - Use `UpperCamelCase` for enum variants
148- [`name-funcs-snake`](rules/name-funcs-snake.md) - Use `snake_case` for functions, methods, modules
149- [`name-consts-screaming`](rules/name-consts-screaming.md) - Use `SCREAMING_SNAKE_CASE` for constants/statics
150- [`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 conversion
153- [`name-to-expensive`](rules/name-to-expensive.md) - `to_` prefix: expensive conversion
154- [`name-into-ownership`](rules/name-into-ownership.md) - `into_` prefix: ownership transfer
155- [`name-no-get-prefix`](rules/name-no-get-prefix.md) - No `get_` prefix for simple getters
156- [`name-is-has-bool`](rules/name-is-has-bool.md) - Use `is_`, `has_`, `can_` for boolean methods
157- [`name-iter-convention`](rules/name-iter-convention.md) - Use `iter`/`iter_mut`/`into_iter` for iterators
158- [`name-iter-method`](rules/name-iter-method.md) - Name iterator methods consistently
159- [`name-iter-type-match`](rules/name-iter-type-match.md) - Iterator type names match method
160- [`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` suffix
162
163### 8. Type Safety (MEDIUM)
164
165- [`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 states
168- [`type-option-nullable`](rules/type-option-nullable.md) - Use `Option<T>` for nullable values
169- [`type-result-fallible`](rules/type-result-fallible.md) - Use `Result<T, E>` for fallible operations
170- [`type-phantom-marker`](rules/type-phantom-marker.md) - Use `PhantomData<T>` for type-level markers
171- [`type-never-diverge`](rules/type-never-diverge.md) - Use `!` type for functions that never return
172- [`type-generic-bounds`](rules/type-generic-bounds.md) - Add trait bounds only where needed
173- [`type-no-stringly`](rules/type-no-stringly.md) - Avoid stringly-typed APIs, use enums/newtypes
174- [`type-repr-transparent`](rules/type-repr-transparent.md) - Use `#[repr(transparent)]` for FFI newtypes
175
176### 9. Testing (MEDIUM)
177
178- [`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 modules
180- [`test-integration-dir`](rules/test-integration-dir.md) - Put integration tests in `tests/` directory
181- [`test-descriptive-names`](rules/test-descriptive-names.md) - Use descriptive test names
182- [`test-arrange-act-assert`](rules/test-arrange-act-assert.md) - Structure tests as arrange/act/assert
183- [`test-proptest-properties`](rules/test-proptest-properties.md) - Use `proptest` for property-based testing
184- [`test-mockall-mocking`](rules/test-mockall-mocking.md) - Use `mockall` for trait mocking
185- [`test-mock-traits`](rules/test-mock-traits.md) - Use traits for dependencies to enable mocking
186- [`test-fixture-raii`](rules/test-fixture-raii.md) - Use RAII pattern (Drop) for test cleanup
187- [`test-tokio-async`](rules/test-tokio-async.md) - Use `#[tokio::test]` for async tests
188- [`test-should-panic`](rules/test-should-panic.md) - Use `#[should_panic]` for panic tests
189- [`test-criterion-bench`](rules/test-criterion-bench.md) - Use `criterion` for benchmarking
190- [`test-doctest-examples`](rules/test-doctest-examples.md) - Keep doc examples as executable tests
191
192### 10. Documentation (MEDIUM)
193
194- [`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 documentation
196- [`doc-examples-section`](rules/doc-examples-section.md) - Include `# Examples` with runnable code
197- [`doc-errors-section`](rules/doc-errors-section.md) - Include `# Errors` for fallible functions
198- [`doc-panics-section`](rules/doc-panics-section.md) - Include `# Panics` for panicking functions
199- [`doc-safety-section`](rules/doc-safety-section.md) - Include `# Safety` for unsafe functions
200- [`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 code
202- [`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 docs
204- [`doc-cargo-metadata`](rules/doc-cargo-metadata.md) - Fill `Cargo.toml` metadata
205
206### 11. Performance Patterns (MEDIUM)
207
208- [`perf-iter-over-index`](rules/perf-iter-over-index.md) - Prefer iterators over manual indexing
209- [`perf-iter-lazy`](rules/perf-iter-lazy.md) - Keep iterators lazy, collect() only when needed
210- [`perf-collect-once`](rules/perf-collect-once.md) - Don't `collect()` intermediate iterators
211- [`perf-entry-api`](rules/perf-entry-api.md) - Use `entry()` API for map insert-or-update
212- [`perf-drain-reuse`](rules/perf-drain-reuse.md) - Use `drain()` to reuse allocations
213- [`perf-extend-batch`](rules/perf-extend-batch.md) - Use `extend()` for batch insertions
214- [`perf-chain-avoid`](rules/perf-chain-avoid.md) - Avoid `chain()` in hot loops
215- [`perf-collect-into`](rules/perf-collect-into.md) - Use `collect_into()` for reusing containers
216- [`perf-black-box-bench`](rules/perf-black-box-bench.md) - Use `black_box()` in benchmarks
217- [`perf-release-profile`](rules/perf-release-profile.md) - Optimize release profile settings
218- [`perf-profile-first`](rules/perf-profile-first.md) - Profile before optimizing
219
220### 12. Project Structure (LOW)
221
222- [`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 type
224- [`proj-flat-small`](rules/proj-flat-small.md) - Keep small projects flat
225- [`proj-mod-rs-dir`](rules/proj-mod-rs-dir.md) - Use `mod.rs` for multi-file modules
226- [`proj-pub-crate-internal`](rules/proj-pub-crate-internal.md) - Use `pub(crate)` for internal APIs
227- [`proj-pub-super-parent`](rules/proj-pub-super-parent.md) - Use `pub(super)` for parent-only visibility
228- [`proj-pub-use-reexport`](rules/proj-pub-use-reexport.md) - Use `pub use` for clean public API
229- [`proj-prelude-module`](rules/proj-prelude-module.md) - Create `prelude` module for common imports
230- [`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 projects
232- [`proj-workspace-deps`](rules/proj-workspace-deps.md) - Use workspace dependency inheritance
233
234### 13. Clippy & Linting (LOW)
235
236- [`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` selectively
242- [`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 crates
245- [`lint-rustfmt-check`](rules/lint-rustfmt-check.md) - Run `cargo fmt --check` in CI
246- [`lint-workspace-lints`](rules/lint-workspace-lints.md) - Configure lints at workspace level
247
248### 14. Anti-patterns (REFERENCE)
249
250- [`anti-unwrap-abuse`](rules/anti-unwrap-abuse.md) - Don't use `.unwrap()` in production code
251- [`anti-expect-lazy`](rules/anti-expect-lazy.md) - Don't use `.expect()` for recoverable errors
252- [`anti-clone-excessive`](rules/anti-clone-excessive.md) - Don't clone when borrowing works
253- [`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` works
255- [`anti-vec-for-slice`](rules/anti-vec-for-slice.md) - Don't accept `&Vec<T>` when `&[T]` works
256- [`anti-index-over-iter`](rules/anti-index-over-iter.md) - Don't use indexing when iterators work
257- [`anti-panic-expected`](rules/anti-panic-expected.md) - Don't panic on expected/recoverable errors
258- [`anti-empty-catch`](rules/anti-empty-catch.md) - Don't use empty `if let Err(_) = ...` blocks
259- [`anti-over-abstraction`](rules/anti-over-abstraction.md) - Don't over-abstract with excessive generics
260- [`anti-premature-optimize`](rules/anti-premature-optimize.md) - Don't optimize before profiling
261- [`anti-type-erasure`](rules/anti-type-erasure.md) - Don't use `Box<dyn Trait>` when `impl Trait` works
262- [`anti-format-hot-path`](rules/anti-format-hot-path.md) - Don't use `format!()` in hot paths
263- [`anti-collect-intermediate`](rules/anti-collect-intermediate.md) - Don't `collect()` intermediate iterators
264- [`anti-stringly-typed`](rules/anti-stringly-typed.md) - Don't use strings for structured data
265
266---
267
268## Recommended Cargo.toml Settings
269
270```toml
271[profile.release]
272opt-level = 3
273lto = "fat"
274codegen-units = 1
275panic = "abort"
276strip = true
277
278[profile.bench]
279inherits = "release"
280debug = true
281strip = false
282
283[profile.dev]
284opt-level = 0
285debug = true
286
287[profile.dev.package."*"]
288opt-level = 3 # Optimize dependencies in dev
289```
290
291---
292
293## How to Use
294
295This skill provides rule identifiers for quick reference. When generating or reviewing Rust code:
296
2971. **Check relevant category** based on task type
2982. **Apply rules** with matching prefix
2993. **Prioritize** CRITICAL > HIGH > MEDIUM > LOW
3004. **Read rule files** in `rules/` for detailed examples
301
302### Rule Application by Task
303
304| Task | Primary Categories |
305|------|-------------------|
306| New function | `own-`, `err-`, `name-` |
307| New struct/API | `api-`, `type-`, `doc-` |
308| Async code | `async-`, `own-` |
309| Error handling | `err-`, `api-` |
310| Memory optimization | `mem-`, `own-`, `perf-` |
311| Performance tuning | `opt-`, `mem-`, `perf-` |
312| Code review | `anti-`, `lint-` |
313
314---
315
316## Sources
317
318This skill synthesizes best practices from:
319- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)
320- [Rust Performance Book](https://nnethercote.github.io/perf-book/)
321- [Rust Design Patterns](https://rust-unofficial.github.io/patterns/)
322- Production codebases: ripgrep, tokio, serde, polars, axum, deno
323- Clippy lint documentation
324- Community conventions (2024-2025)