
Rust Skills
- 3.6k installs
- 367 repo stars
- Updated June 14, 2026
- leonardomso/rust-skills
rust-skills is a comprehensive Rust coding guideline skill with 265 prioritized rules across 26 categories.
About
Rust Skills is a comprehensive guideline set with 265 rules across 26 categories prioritized by impact for Rust 1.96 and the 2024 edition. Critical tiers cover ownership and borrowing, error handling with thiserror and anyhow patterns, memory optimization including SmallVec and zero-copy slices, and unsafe code safety comments with Miri CI guidance. High-priority sections span API design, async await, concurrency, compiler optimization, and numeric safety. Medium tiers address type safety, traits, serde, pattern matching, macros, closures, collections, naming, testing, documentation, observability, and performance patterns. Each rule links to a dedicated markdown file such as own-borrow-over-clone and err-no-unwrap-prod. The skill targets new modules, public API design, hot path tuning, and code review for borrowing and allocation issues. Sources include Rust API Guidelines, Performance Book, Rustonomicon, and production codebases like tokio, serde, and axum.
- 265 rules across 26 categories with impact priority.
- Critical ownership, error, memory, and unsafe sections first.
- Linked rule files such as own-borrow-over-clone and err-no-unwrap-prod.
- Async, concurrency, and API design high-priority guidance.
- Current for Rust 1.96 and 2024 edition patterns.
Rust Skills by the numbers
- 3,611 all-time installs (skills.sh)
- +689 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #6 of 129 Rust skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
rust-skills capabilities & compatibility
- Capabilities
- ownership and borrowing rule catalog · error handling with result and custom types · memory and allocation optimization patterns · unsafe code safety and miri guidance · async await and concurrency best practices · api design and documentation conventions
- Use cases
- code review · refactoring · api development
- Pricing
- Free
What rust-skills says it does
Contains 265 rules across 26 categories, prioritized by impact
npx skills add https://github.com/leonardomso/rust-skills --skill rust-skillsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3.6k |
|---|---|
| repo stars | ★ 367 |
| Security audit | 3 / 3 scanners passed |
| Last updated | June 14, 2026 |
| Repository | leonardomso/rust-skills ↗ |
What idiomatic Rust patterns should I follow for ownership, errors, async, and performance?
Apply 265 prioritized Rust rules across ownership, errors, async, unsafe, API design, and performance when writing or reviewing code.
Who is it for?
Rust developers writing, reviewing, or refactoring production Rust modules and public APIs.
Skip if: Skip for non-Rust languages, beginner syntax tutorials, or cargo install help only.
When should I use this skill?
User writes Rust code, reviews borrowing, async, unsafe, serde, or performance hot paths.
What you get
Code aligned to prioritized rust-skills rules for the relevant category and hot paths.
- Idiomatic Rust code
- Review guidance
By the numbers
- Contains 179 rules across 14 categories
- Version 1.0.0 under MIT license
Files
Rust Best Practices
Comprehensive guide for writing high-quality, idiomatic, and highly optimized Rust code. Contains 265 rules across 26 categories, prioritized by impact to guide LLMs in code generation and refactoring. Current for Rust 1.96 (2024 edition).
When to Apply
Reference these guidelines when:
- Writing new Rust functions, structs, or modules
- Implementing error handling or async code
- Writing concurrent, parallel, or
unsafecode - 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- | 17 |
| 4 | Unsafe Code | CRITICAL | unsafe- | 7 |
| 5 | API Design | HIGH | api- | 17 |
| 6 | Async/Await | HIGH | async- | 18 |
| 7 | Concurrency | HIGH | conc- | 4 |
| 8 | Compiler Optimization | HIGH | opt- | 12 |
| 9 | Numeric & Arithmetic Safety | HIGH | num- | 5 |
| 10 | Type Safety | MEDIUM | type- | 13 |
| 11 | Trait & Generics Design | MEDIUM | trait- | 6 |
| 12 | Conversions | MEDIUM | conv- | 3 |
| 13 | Const & Compile-Time | MEDIUM | const- | 4 |
| 14 | Serde | MEDIUM | serde- | 8 |
| 15 | Pattern Matching | MEDIUM | pat- | 5 |
| 16 | Macros | MEDIUM | macro- | 8 |
| 17 | Closures | MEDIUM | closure- | 5 |
| 18 | Collections | MEDIUM | coll- | 4 |
| 19 | Naming Conventions | MEDIUM | name- | 16 |
| 20 | Testing | MEDIUM | test- | 15 |
| 21 | Documentation | MEDIUM | doc- | 12 |
| 22 | Observability | MEDIUM | obs- | 7 |
| 23 | Performance Patterns | MEDIUM | perf- | 13 |
| 24 | Project Structure | LOW | proj- | 14 |
| 25 | Clippy & Linting | LOW | lint- | 13 |
| 26 | Anti-patterns | REFERENCE | anti- | 15 |
---
Quick Reference
1. Ownership & Borrowing (CRITICAL)
- `own-borrow-over-clone` - Prefer
&Tborrowing over.clone() - `own-slice-over-vec` - Accept
&[T]not&Vec<T>,&strnot&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 shared ownership in single-threaded contexts - `own-refcell-interior` - Use
RefCell<T>for interior mutability in single-threaded code - `own-mutex-interior` - Use
Mutex<T>for interior mutability across threads - `own-rwlock-readers` - Use
RwLock<T>when reads significantly outnumber writes - `own-copy-small` - Implement
Copyfor small, simple types - `own-clone-explicit` - Use explicit
Clonefor types where copying has meaningful cost - `own-move-large` - Move large types instead of copying; use
Boxif moves are expensive - `own-lifetime-elision` - Rely on lifetime elision rules; add explicit lifetimes only when required
2. Error Handling (CRITICAL)
- `err-thiserror-lib` - Use
thiserrorfor library error types - `err-anyhow-app` - Use
anyhowfor application error handling - `err-result-over-panic` - Return
Result<T, E>instead of panicking for recoverable errors - `err-context-chain` - Add context with
.context()or.with_context() - `err-no-unwrap-prod` - Avoid
unwrap()in production code; use?,expect(), or handle errors - `err-expect-bugs-only` - Use
expect()only for invariants that indicate bugs, not user errors - `err-question-mark` - Use
?operator for clean propagation - `err-from-impl` - Implement
From<E>for error conversions to enable?operator - `err-source-chain` - Preserve error chains with
#[source]orsource()method - `err-lowercase-msg` - Start error messages lowercase, no trailing punctuation
- `err-doc-errors` - Document error conditions with
# Errorssection in doc comments - `err-custom-type` - Define custom error types for domain-specific failures
3. Memory Optimization (CRITICAL)
- `mem-with-capacity` - Use
with_capacity()when size is known - `mem-smallvec` - Use
SmallVecfor usually-small collections - `mem-arrayvec` - Use
ArrayVec<T, N>for fixed-capacity collections that never heap-allocate - `mem-box-large-variant` - Box large enum variants to reduce overall enum size
- `mem-boxed-slice` - Use
Box<[T]>instead ofVec<T>for fixed-size heap data - `mem-thinvec` - Use
ThinVec<T>for nullable collections with minimal overhead - `mem-clone-from` - Use
clone_from()to reuse allocations when repeatedly cloning - `mem-reuse-collections` - Clear and reuse collections instead of creating new ones in loops
- `mem-avoid-format` - Avoid
format!()when string literals work - `mem-write-over-format` - Use
write!()into existing buffers instead offormat!()allocations - `mem-arena-allocator` - Use arena allocators for batch allocations
- `mem-zero-copy` - Use zero-copy patterns with slices and
Bytes - `mem-compact-string` - Use compact string types for memory-constrained string storage
- `mem-smaller-integers` - Use appropriately-sized integers to reduce memory footprint
- `mem-assert-type-size` - Use static assertions to guard against accidental type size growth
- `mem-take-replace` - Use
mem::take/mem::replaceto move a value out of a&mutwithout cloning - `mem-drop-order` - Know and control drop order: struct fields drop top-to-bottom, locals in reverse
4. Unsafe Code (CRITICAL)
- `unsafe-safety-comment` - Write a
// SAFETY:comment above everyunsafeblock and a# Safetysection in everyunsafe fn. - `unsafe-minimize-scope` - Keep
unsafeblocks as small as possible — mark only the operation that requires unsafety, not the surrounding safe code. - `unsafe-miri-ci` - Run
cargo miri testin CI for every crate that containsunsafecode. - `unsafe-maybeuninit` - Use
MaybeUninit<T>for uninitialized memory; never usemem::uninitialized()ormem::zeroed()for types with validity invariants. - `unsafe-extern-block` - In Rust 2024, wrap
externblocks inunsafe extern { }and annotate each item assafeorunsafe. - `unsafe-send-sync-manual` - Document the invariants when manually implementing
SendorSync; prefer letting the compiler derive them automatically. - `unsafe-no-mangle-unsafe` - In Rust 2024, write
#[unsafe(no_mangle)],#[unsafe(export_name = "...")], and#[unsafe(link_section = "...")]— not the bare attribute forms.
5. API Design (HIGH)
- `api-builder-pattern` - Use Builder pattern for complex construction
- `api-builder-must-use` - Mark builder methods with
#[must_use]to prevent silent drops - `api-newtype-safety` - Use newtypes to prevent mixing semantically different values
- `api-typestate` - Use typestate pattern to encode state machine invariants in the type system
- `api-sealed-trait` - Use sealed traits to prevent external implementations while allowing use
- `api-extension-trait` - Use extension traits to add methods to external types
- `api-parse-dont-validate` - Parse into validated types at boundaries
- `api-impl-into` - Accept
impl Into<T>for flexible APIs, implementFrom<T>for conversions - `api-impl-asref` - Use
AsRef<T>when you only need to borrow the inner data - `api-must-use` - Mark types and functions with
#[must_use]when ignoring results is likely a bug - `api-non-exhaustive` - Use
#[non_exhaustive]on public enums and structs for forward compatibility - `api-from-not-into` - Implement
From<T>, notInto<U>- From gives you Into for free - `api-default-impl` - Implement
Defaultfor types with sensible default values - `api-common-traits` - Implement standard traits (Debug, Clone, PartialEq, etc.) for public types
- `api-serde-optional` - Make serde a feature flag, not a hard dependency for library crates
- `api-impl-fromiterator` - Implement
FromIteratorandExtendfor collection types, andIntoIteratorfor all three reference forms - `api-operator-overload` - Overload operators only when the semantics are natural and unsurprising
6. Async/Await (HIGH)
- `async-tokio-runtime` - Configure Tokio runtime appropriately for your workload
- `async-no-lock-await` - Never hold
Mutex/RwLockacross.await - `async-spawn-blocking` - Use
spawn_blockingfor CPU-intensive work - `async-tokio-fs` - Use
tokio::fsinstead ofstd::fsin async code - `async-cancellation-token` - Use
CancellationTokenfor graceful shutdown and task cancellation - `async-join-parallel` - Use
join!ortry_join!for concurrent independent futures - `async-try-join` - Use
try_join!for concurrent fallible operations with early return on error - `async-select-racing` - Use
select!to race futures and handle the first to complete - `async-bounded-channel` - Use bounded channels to apply backpressure and prevent unbounded memory growth
- `async-mpsc-queue` - Use
mpscchannels for async message queues between tasks - `async-broadcast-pubsub` - Use
broadcastchannel for pub/sub where all subscribers receive all messages - `async-watch-latest` - Use
watchchannel for sharing the latest value with multiple observers - `async-oneshot-response` - Use
oneshotchannel for request-response patterns - `async-joinset-structured` - Use
JoinSetfor managing dynamic collections of spawned tasks - `async-clone-before-await` - Clone Arc/Rc data before await points to avoid holding references across suspension
- `async-fn-in-trait` - Use native
async fnin traits (stable 1.75) instead of theasync_traitmacro - `async-async-fn-bounds` - Use
AsyncFn/AsyncFnMut/AsyncFnOncebounds instead ofF: Fn() -> Fut, Fut: Future - `async-cancel-safety` - Ensure futures used in
tokio::select!branches are cancellation-safe
7. Concurrency (HIGH)
- `conc-rayon-par-iter` - Use rayon's
par_iter()for CPU-bound data parallelism - `conc-scoped-threads` - Use
std::thread::scopeto borrow stack data across threads - `conc-atomic-ordering` - Use the weakest correct memory
Orderingfor every atomic operation - `conc-thread-local` - Prefer
thread_local!withCell/RefCelloverstatic mut
8. Compiler Optimization (HIGH)
- `opt-inline-small` - Use
#[inline]for small hot functions - `opt-inline-always-rare` - Use
#[inline(always)]sparingly—only for critical hot paths proven by profiling - `opt-inline-never-cold` - Use
#[inline(never)]and#[cold]for error paths and rarely-executed code - `opt-cold-unlikely` - Mark unlikely code paths with
#[cold]to help compiler optimization - `opt-likely-hint` - Use code structure to hint at likely branches; use intrinsics on nightly
- `opt-lto-release` - Enable LTO in release builds
- `opt-codegen-units` - Set
codegen-units = 1for maximum optimization in release builds - `opt-pgo-profile` - Use Profile-Guided Optimization (PGO) for maximum performance
- `opt-target-cpu` - Use
target-cpu=nativefor maximum performance on known deployment targets - `opt-bounds-check` - Use iterators and patterns that eliminate bounds checks in hot paths
- `opt-simd-portable` - Use portable SIMD for vectorized operations across architectures
- `opt-cache-friendly` - Organize data for cache-efficient access patterns
9. Numeric & Arithmetic Safety (HIGH)
- `num-overflow-explicit` - Handle integer overflow explicitly:
checked_/saturating_/wrapping_/overflowing_ - `num-cast-try-from` - Avoid
asfor narrowing casts; useFromfor widening andTryFromfor narrowing - `num-float-compare` - Don't compare floats with
==; use a tolerance, andtotal_cmpfor ordering - `num-saturating-clamp` - Bound values with
clampand saturating arithmetic - `num-nonzero` - Use
NonZero*types to forbid zero and unlock the niche optimization
10. Type Safety (MEDIUM)
- `type-newtype-ids` - Wrap IDs in newtypes:
UserId(u64) - `type-newtype-validated` - Use newtypes to enforce validation at construction time
- `type-enum-states` - Use enums for mutually exclusive states
- `type-option-nullable` - Use
Option<T>for values that might not exist - `type-result-fallible` - Use
Result<T, E>for operations that can fail - `type-phantom-marker` - Use
PhantomDatato express type relationships without runtime cost - `type-never-diverge` - Use
!(never type) for functions that never return - `type-generic-bounds` - Add trait bounds only where needed, prefer where clauses for readability
- `type-no-stringly` - Avoid stringly-typed APIs; use enums, newtypes, or validated types
- `type-repr-transparent` - Use
#[repr(transparent)]for newtypes in FFI contexts - `type-deref-coercion` - Implement
Deref/DerefMutonly for smart-pointer and transparent wrapper types - `type-display-vs-debug` - Use
Displayfor user-facing output andDebugfor diagnostics; never swap them - `type-numeric-fmt` - Implement
LowerHex,UpperHex,Octal, andBinaryfor numeric newtypes
11. Trait & Generics Design (MEDIUM)
- `trait-associated-type-vs-generic` - Use an associated type when each impl has exactly one output type; use a generic parameter when a type can implement the trait for many input types
- `trait-blanket-impl` - Use a blanket impl
impl<T: Bound> Trait for Tto give behaviour to every type that satisfies a bound - `trait-coherence-newtype` - Respect the orphan rule; wrap a foreign type in a newtype to implement a foreign trait on it
- `trait-default-methods` - Define a trait in terms of a few required methods plus defaulted ones built on top of them
- `trait-dyn-vs-generic` - Choose static dispatch (generics /
impl Trait) vs dynamic dispatch (dyn Trait) deliberately - `trait-object-safety` - Keep a trait dyn-compatible (object-safe) when you need
dyn Trait
12. Conversions (MEDIUM)
- `conv-tryfrom-fallible` - Implement
TryFromfor fallible conversions instead of ad-hoc conversion functions - `conv-fromstr-parsing` - Implement
FromStrto enablestr::parsefor string-to-type conversions - `conv-asmut-mutable` - Accept
impl AsMut<T>for flexible mutable borrowed inputs instead of concrete mutable references
13. Const & Compile-Time (MEDIUM)
- `const-block` - Use inline
const { }blocks for compile-time evaluation and assertions - `const-fn` - Make functions
const fnwhen they can run at compile time - `const-generics` - Parameterize over values with const generics
<const N: usize> - `const-vs-static` - Use
constfor an inlined value andstaticfor a single addressed instance
14. Serde (MEDIUM)
- `serde-rename-all` - Match the external naming convention with
#[serde(rename_all = ...)] - `serde-default-compat` - Use
#[serde(default)]for optional and backward-compatible fields - `serde-skip-empty` - Omit empty fields with
skip_serializing_if - `serde-flatten` - Inline nested structs or capture extra keys with
#[serde(flatten)] - `serde-enum-representation` - Choose enum tagging deliberately: externally, internally, adjacently tagged, or untagged
- `serde-deny-unknown-fields` - Reject unexpected keys with
#[serde(deny_unknown_fields)] - `serde-custom-with` - Customize a field's (de)serialization with
with/serialize_with/deserialize_with - `serde-try-from-validate` - Validate while deserializing with
#[serde(try_from = "Raw")]
15. Pattern Matching (MEDIUM)
- `pat-let-else` - Use
let ... elsefor early-return pattern extraction - `pat-matches-macro` - Use
matches!()for boolean pattern tests - `pat-if-let-chains` - Use
if letchains to combine pattern bindings and conditions - `pat-exhaustive-enum` - Match owned enums exhaustively; avoid catch-all
_that hides new variants - `pat-at-bindings` - Use
@bindings to capture a value while matching it against a pattern
16. Macros (MEDIUM)
- `macro-prefer-functions` - Reach for a macro only when a function or generic cannot express it
- `macro-rules-hygiene` - Rely on
macro_rules!hygiene and use$cratefor paths to your crate's items - `macro-fragment-specifiers` - Capture with precise fragment specifiers, not raw
:tt, where you can - `macro-export-crate-path` - Export declarative macros with
#[macro_export]and a clean import path - `macro-private-helpers` - Hide macro-generated helper items behind a
#[doc(hidden)] pub mod __private - `macro-proc-two-crate` - Put procedural macros in a dedicated
proc-macro = truecrate and re-export from the facade - `macro-proc-syn-quote` - Build procedural macros with
syn,quote, andproc-macro2 - `macro-proc-error-spans` - Report proc-macro errors as spanned compile errors, never by panicking
17. Closures (MEDIUM)
- `closure-fn-trait-bounds` - Require the least restrictive
Fntrait a callback needs (FnOnce⊇FnMut⊇Fn) - `closure-impl-fn-return` - Return closures as
impl Fn/FnMut/FnOnce, notBox<dyn Fn> - `closure-move-capture` - Use
movefor closures that outlive the current scope; clone beforemoveto keep the original - `closure-static-vs-dyn` - Accept
impl Fn(generic) for hot callbacks; use&dyn Fn/Box<dyn Fn>to cut code size or to store them - `closure-disjoint-capture` - Capture only what you use; lean on edition-2021 disjoint closure captures
18. Collections (MEDIUM)
- `coll-binaryheap` - Use
BinaryHeapfor a priority queue or repeated max-extraction - `coll-map-choice` - Pick the map by access pattern:
HashMap(fast, unordered),BTreeMap(sorted / range queries),IndexMap(insertion order) - `coll-seq-choice` - Default to
Vec; useVecDequefor queue/deque behaviour; avoidLinkedList - `coll-set-membership` - Use
HashSet/BTreeSetfor membership tests and dedup, not linearVec::contains
19. Naming Conventions (MEDIUM)
- `name-types-camel` - Use
UpperCamelCasefor types, traits, and enum names - `name-variants-camel` - Use
UpperCamelCasefor enum variants - `name-funcs-snake` - Use
snake_casefor functions, methods, variables, and modules - `name-consts-screaming` - Use
SCREAMING_SNAKE_CASEfor constants and statics - `name-lifetime-short` - Use short, conventional lifetime names:
'a,'b,'de,'src - `name-type-param-single` - Use single uppercase letters for type parameters:
T,E,K,V - `name-as-free` -
as_prefix: free reference conversion - `name-to-expensive` - Use
to_prefix for expensive conversions that allocate or compute - `name-into-ownership` - Use
into_prefix for ownership-consuming conversions - `name-no-get-prefix` - Omit get_ prefix for simple getters
- `name-is-has-bool` - Use
is_,has_,can_,should_prefixes for boolean-returning methods - `name-iter-convention` - Use iter/iter_mut/into_iter for iterator methods
- `name-iter-method` - Name iterator methods
iter(),iter_mut(), andinto_iter()consistently - `name-iter-type-match` - Name iterator types after their source method
- `name-acronym-word` - Treat acronyms as words in identifiers:
HttpServer, notHTTPServer - `name-crate-no-rs` - Don't suffix crate names with
-rsor-rust
20. Testing (MEDIUM)
- `test-cfg-test-module` - Put unit tests in
#[cfg(test)] mod tests { }within each module - `test-use-super` - Use
use super::*;in test modules to access parent module items - `test-integration-dir` - Put integration tests in the
tests/directory - `test-descriptive-names` - Use descriptive test names that explain what is being tested
- `test-arrange-act-assert` - Structure tests with clear Arrange, Act, Assert sections
- `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 in tests
- `test-fixture-raii` - Use RAII pattern (Drop trait) for automatic test cleanup
- `test-tokio-async` - Use
#[tokio::test]for async tests - `test-should-panic` - Use
#[should_panic]to test that code panics as expected - `test-criterion-bench` - Use
criterionfor benchmarking - `test-doctest-examples` - Keep documentation examples as executable doctests
- `test-loom-concurrency` - Use
loomto exhaustively test lock-free and concurrent code - `test-snapshot-testing` - Use snapshot testing (insta) for complex or serialized output
21. Documentation (MEDIUM)
- `doc-all-public` - Document all public items with
///doc comments - `doc-module-inner` - Use
//!for module-level documentation - `doc-examples-section` - Include
# Exampleswith runnable code - `doc-errors-section` - Include
# Errorssection for fallible functions - `doc-panics-section` - Include
# Panicssection for functions that can panic - `doc-safety-section` - Include
# Safetysection 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 to reference types and items
- `doc-link-types` - Use intra-doc links to connect related types and functions
- `doc-cargo-metadata` - Fill
Cargo.tomlmetadata for published crates - `doc-crate-readme` - Unify the README and crate root docs with
#![doc = include_str!("../README.md")]
22. Observability (MEDIUM)
- `obs-tracing-over-log` - Use
tracingfor structured, span-aware diagnostics instead ofprintln!or barelog - `obs-library-facade` - Libraries emit through the tracing/log facade and never install a subscriber
- `obs-structured-fields` - Record structured key-value fields, not values interpolated into the message string
- `obs-instrument-spans` - Use
#[tracing::instrument]and spans to attach context to async tasks and requests - `obs-levels-filter` - Use log levels meaningfully and filter with
EnvFilter/RUST_LOG - `obs-error-chain` - Log errors with their full source chain, and log each error exactly once
- `obs-no-sensitive-data` - Never log secrets or PII; redact or skip them
23. 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
- `perf-ahash` - Use a faster hasher (
ahash/FxHashMap) when DoS resistance is not needed - `perf-io-buffering` - Wrap
Read/WriteinBufReader/BufWriterfor many small operations
24. Project Structure (LOW)
- `proj-lib-main-split` - Keep
main.rsminimal, logic inlib.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 for consistent versions across crates
- `proj-feature-additive` - Design Cargo features to be strictly additive
- `proj-msrv-declare` - Declare
rust-version(MSRV) in Cargo.toml and test it in CI - `proj-build-rs-minimal` - Keep
build.rsminimal, deterministic, and idempotent
25. Clippy & Linting (LOW)
- `lint-deny-correctness` -
#![deny(clippy::correctness)] - `lint-warn-suspicious` - Enable clippy::suspicious for likely bugs
- `lint-warn-style` - Enable clippy::style for idiomatic code
- `lint-warn-complexity` - Enable clippy::complexity for simpler code
- `lint-warn-perf` - Enable clippy::perf for performance improvements
- `lint-pedantic-selective` - Enable clippy::pedantic selectively
- `lint-missing-docs` - Warn on missing documentation for public items
- `lint-unsafe-doc` - Require documentation for unsafe blocks
- `lint-cargo-metadata` - Enable clippy::cargo for published crates
- `lint-rustfmt-check` - Run cargo fmt --check in CI
- `lint-workspace-lints` - Configure lints at workspace level for consistent enforcement
- `lint-cfg-check` - Enable
unexpected_cfgsand declare known cfgs to catch feature-gate typos - `lint-clippy-nursery-selected` - Enable high-value
clippy::nurserylints selectively, not the whole group
26. 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 points
- `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 or recoverable errors
- `anti-empty-catch` - Don't silently ignore errors
- `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 where enums or newtypes would provide type safety
---
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:
1. Check relevant category based on task type 2. Apply rules with matching prefix 3. Prioritize CRITICAL > HIGH > MEDIUM > LOW 4. Read rule files in rules/ for detailed examples
Rule Application by Task
| Task | Primary Categories |
|---|---|
| New function | own-, err-, name-, pat- |
| New struct/API | api-, type-, conv-, doc- |
| Async code | async-, own- |
| Concurrency / parallelism | conc-, async-, own- |
| Unsafe code | unsafe-, type-, test- |
| Error handling | err-, api-, pat- |
| Type conversions | conv-, api- |
| Serialization (serde) | serde-, type-, api- |
| Numeric / arithmetic | num-, type- |
| Macros / code generation | macro-, anti- |
| Closures / callbacks | closure-, type- |
| Logging / observability | obs-, err- |
| Memory optimization | mem-, own-, perf- |
| Performance tuning | opt-, mem-, perf- |
| Code review | anti-, lint- |
---
Sources & Attribution
This skill is an independent synthesis of official Rust guidance, well-known books, and patterns from widely-used crates. It is not affiliated with or endorsed by the Rust project or any crate author; the text and code examples are original.
Official Rust documentation
- The Rust Reference
- Rust API Guidelines
- The Rustonomicon (unsafe code)
- Rust 2024 Edition Guide
- The Cargo Book
- Standard library docs and release notes
Books & guides
- The Rust Performance Book — Nicholas Nethercote
- Rust Design Patterns — rust-unofficial
- Rust Atomics and Locks — Mara Bos
- Effective Rust — David Drysdale
Tooling
Real-world codebases studied for idioms
- ripgrep, tokio, serde, clap, polars, axum, cargo, hyper, bevy, rayon, and dtolnay's crates (thiserror, anyhow, syn)
This project is MIT-licensed. Referenced upstream materials remain under their own licenses (the official Rust docs and API Guidelines are dual MIT / Apache-2.0).
name: CI
on:
push:
branches: [master]
pull_request:
permissions:
contents: read
jobs:
checks:
name: Validate & compile-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
# Toolchain/target are pinned by checks/rust-toolchain.toml (Rust 1.95.0).
- uses: dtolnay/rust-toolchain@1.95.0
with:
targets: x86_64-unknown-linux-gnu
- uses: Swatinem/rust-cache@v2
with:
workspaces: checks
# The exact same command contributors run locally.
- name: Run checks
run: bash checks/check.sh
SKILL.md
Changelog
All notable changes to this skill are documented here. The format is based on Keep a Changelog, and the project aims to follow semantic versioning for the rule set.
[1.5.1]
Changed
- Depth pass: expanded
own-rc-single-thread(breaking cycles withWeak, the
Rc::clone idiom, strong_count/weak_count, !Send/!Sync) and own-refcell-interior (Cell for Copy types).
- Added cross-references from ~18 foundational rules to the newer categories
(conc-, conv-, num-, serde-, trait-, closure-, coll-, pat-) for better navigation between related rules.
[1.5.0]
Added
- Const & Compile-Time category (
const-, 4 rules):const fn,constvs
static, const generics, inline const { } blocks.
- Trait & Generics Design category (
trait-, 6 rules): static vs dynamic
dispatch, associated types vs generic params, default methods, blanket impls, object safety, the orphan rule + newtype.
- Collections category (
coll-, 4 rules): map choice (HashMap/BTreeMap/
IndexMap), sequence choice (Vec/VecDeque), set membership, BinaryHeap.
checks/gen_index.py— generatesSKILL.md's priority table and Quick
Reference (and the rule counts) from rules/ so the index can't drift; CI runs it in --check mode.
CONTRIBUTING.mdand thisCHANGELOG.md.
Now 265 rules across 26 categories.
[1.4.0]
Added
- Closures category (
closure-, 5 rules): Fn/FnMut/FnOnce bounds, returning
impl Fn, move capture, static vs dynamic dispatch, disjoint capture.
Now 251 rules across 23 categories.
[1.3.0]
Added
- Serde category (
serde-, 8 rules): rename_all, default, skip, flatten,
enum representation, deny_unknown_fields, custom (de)serialize, validate-on- deserialize.
- Numeric & Arithmetic Safety category (
num-, 5 rules): explicit overflow
handling, as vs TryFrom, float comparison, clamping, NonZero.
Now 246 rules across 22 categories.
[1.2.0]
Added
- Macros category (
macro-, 8 rules): declarative-macro hygiene and
fragment specifiers, and procedural-macro design with syn/quote.
- Observability category (
obs-, 7 rules):tracing, spans, structured
fields, error chains, and keeping secrets out of logs.
Now 233 rules across 20 categories.
[1.1.x]
Added
- Unsafe Code (
unsafe-), Concurrency (conc-), Conversions
(conv-), and Pattern Matching (pat-) categories, plus new rules across existing categories — 39 rules in total.
- A compile-check harness (
checks/) and a GitHub Actions CI workflow that
validates rule structure, links, the index, and that examples compile.
Changed
- Updated throughout for the Rust 2024 edition and current stable (Rust 1.96):
fixed &mut T is not Copy, impl Trait in traits, collect_into status, resolver = "3", env::set_var now unsafe, and more.
Now 218 rules across 18 categories.
[1.0.0]
Added
- Initial release: 179 rules across 14 categories.
[1.5.0]: https://github.com/leonardomso/rust-skills [1.4.0]: https://github.com/leonardomso/rust-skills [1.3.0]: https://github.com/leonardomso/rust-skills [1.2.0]: https://github.com/leonardomso/rust-skills [1.1.x]: https://github.com/leonardomso/rust-skills [1.0.0]: https://github.com/leonardomso/rust-skills
/target
/examples
manifest.json
check*.json
check*.err
suspects.txt
#!/usr/bin/env python3
"""Classify `cargo check --examples --message-format=json` output.
Buckets per example:
FRAGMENT - every error is name resolution (undefined symbol/crate/import).
Expected for illustrative snippets; ignored.
ARTIFACT - errors from extracting a fragment (a `&self` method body wrapped
as a free fn, pseudocode `...`/`???` tokens, dangling doc comments).
LOW - only "type annotations needed" (E0282/E0283).
SUSPECT - anything else (type mismatch, no-method, bad syntax, wrong arity,
missing trait impl, ...). These are real or likely-real bugs.
Modes:
analyze.py check.json print summary + suspect details
analyze.py check.json --emit-baseline print one signature per suspect
analyze.py check.json --check-baseline F exit 1 if any suspect is not in F
A signature is `file :: section :: sorted(error-tokens)` so it is stable across
line-number edits. CI gates on signatures absent from the committed baseline.
"""
import json, sys, pathlib, collections
HERE = pathlib.Path(__file__).resolve().parent
manifest = json.loads((HERE / "manifest.json").read_text())
RES_CODES = {"E0432","E0433","E0412","E0425","E0405","E0531","E0422",
"E0423","E0573","E0463","E0583","E0561","E0658"}
RES_PREFIXES = ("cannot find","unresolved import","failed to resolve",
"use of undeclared","cannot determine","can't find crate",
"maybe a missing crate","unresolved module")
LOW_CODES = {"E0282","E0283"}
def code_of(d):
return (d.get("code") or {}).get("code")
def is_resolution(d):
if code_of(d) in RES_CODES:
return True
m = d.get("message","")
return any(m.startswith(p) for p in RES_PREFIXES)
def is_artifact(d):
m = d.get("message","")
if "parameter is only allowed in associated functions" in m:
return True
if code_of(d) in {"E0586","E0585"}:
return True
if "`...`" in m or "missing documentation" in m:
return True
if "await is only allowed inside" in m:
return True
return False
def token(d):
c = code_of(d)
if c:
return c
# parse errors have no code: use a short normalized message stem
words = d.get("message","").lower().split()
return "P:" + " ".join(words[:5])
def parse(path):
errors = collections.defaultdict(list)
with open(path) as fh:
for raw in fh:
raw = raw.strip()
if not raw.startswith("{"):
continue
try:
rec = json.loads(raw)
except json.JSONDecodeError:
continue
if rec.get("reason") != "compiler-message":
continue
msg = rec.get("message", {})
if msg.get("level") != "error":
continue
tgt = (rec.get("target") or {}).get("name")
if tgt:
errors[tgt].append(msg)
return errors
def classify(errors):
frag = artifact = low = 0
suspects = {}
for ex, diags in errors.items():
nonres = [d for d in diags if not is_resolution(d)]
if not nonres:
frag += 1; continue
if all(is_artifact(d) for d in nonres):
artifact += 1; continue
real = [d for d in nonres if not is_artifact(d)]
if all(code_of(d) in LOW_CODES for d in real):
low += 1; continue
suspects[ex] = [d for d in real if code_of(d) not in LOW_CODES]
return frag, artifact, low, suspects
def signature(ex, diags):
info = manifest.get(ex, {})
toks = ",".join(sorted({token(d) for d in diags}))
return f"{info.get('file','?')} :: {info.get('section','?')} :: {toks}"
def main():
args = sys.argv[1:]
path = next((a for a in args if not a.startswith("--")), "check.json")
errors = parse(path)
frag, artifact, low, suspects = classify(errors)
sigs = sorted({signature(ex, d) for ex, d in suspects.items()})
if "--emit-baseline" in args:
print("\n".join(sigs))
return
if "--check-baseline" in args:
bpath = args[args.index("--check-baseline") + 1]
base = set(l.strip() for l in open(bpath) if l.strip() and not l.startswith("#"))
new = [s for s in sigs if s not in base]
if new:
print(f"FAIL: {len(new)} new compile-suspect(s) not in baseline:\n")
print("\n".join(f" + {s}" for s in new))
print("\nIf these are real bugs, fix the example. If they are new "
"intentional fragments, regenerate the baseline:\n"
" python3 analyze.py check.json --emit-baseline > baseline.txt")
sys.exit(1)
print(f"OK: no new compile suspects ({len(sigs)} known, all in baseline)")
return
checked = len(manifest); failed = len(errors)
print("== compile-check summary ==")
print(f"examples checked : {checked}")
print(f"compiled clean : {checked - failed}")
print(f"fragments (undefined syms): {frag}")
print(f"wrapper/pseudocode artifacts: {artifact}")
print(f"low-signal (needs type ann): {low}")
print(f"SUSPECT (review these) : {len(suspects)}")
print()
rows = []
for ex, diags in suspects.items():
info = manifest.get(ex, {})
rows.append((info.get("file","?"), info.get("line",0), info.get("section","?"), diags))
for file, line, section, diags in sorted(rows):
print(f"\n--- {file}:{line} [{section}]")
seen = set()
for d in diags:
c = code_of(d) or "----"
m = d.get("message","").splitlines()[0]
if (c, m) in seen:
continue
seen.add((c, m))
print(f" {c}: {m}")
if __name__ == "__main__":
main()
anti-format-hot-path.md :: When format! Is Fine :: E0308
anti-lock-across-await.md :: Pattern: Clone Before Await :: E0107
anti-over-abstraction.md :: Prefer Concrete Types in Private Code :: E0428
anti-over-abstraction.md :: Rule of Three :: E0107
anti-premature-optimize.md :: When to Optimize :: E0308
anti-stringly-typed.md :: Good :: E0308
anti-type-erasure.md :: impl Trait Positions :: E0107
anti-unwrap-abuse.md :: Good :: E0267
anti-vec-for-slice.md :: Mutable Slices :: E0428
api-builder-must-use.md :: Good :: E0599
api-builder-pattern.md :: Builder Variations :: E0428
api-common-traits.md :: Manual Implementations :: E0404
api-default-impl.md :: Builder with Default :: E0599
api-extension-trait.md :: Ecosystem Examples :: E0599
api-extension-trait.md :: Scoped Extensions :: P:expected item, found keyword `let`
api-from-not-into.md :: Blanket Implementation :: E0210,P:non-item in item list
api-impl-asref.md :: AsRef vs Into vs Borrow :: E0106,E0404
api-impl-asref.md :: Common AsRef Implementations :: E0117,P:non-item in item list
api-impl-asref.md :: Pattern: Optional AsRef Bound :: E0428
api-impl-into.md :: Implement From, Not Into :: E0119
api-impl-into.md :: When NOT to Use impl Into :: E0562
api-must-use.md :: When to Apply :: P:expected one of `->`, `<`,,P:missing parameters for function definition
api-newtype-safety.md :: Constructor Patterns :: E0204
api-newtype-safety.md :: Good :: E0063,E0308
api-newtype-safety.md :: Zero-Cost Abstraction :: E0308
api-sealed-trait.md :: Full Pattern :: P:missing `fn` or `struct` for,P:non-item in item list
api-serde-optional.md :: Multiple Optional Dependencies :: P:expected `;`, found `#`,P:expected `;`, found `borsh`,P:expected `;`, found `default`,P:expected `;`, found `rkyv`,P:expected `;`, found `serde`,P:expected one of `.`, `;`,
api-serde-optional.md :: When to Make Serde Required :: P:expected `;`, found `serde`
api-typestate.md :: Builder Typestate :: E0599
async-bounded-channel.md :: Worker Pool Pattern :: E0107
async-cancellation-token.md :: CancellationToken API :: E0069
async-cancellation-token.md :: Graceful Shutdown Pattern :: E0107,E0752
async-cancellation-token.md :: Hierarchical Cancellation :: E0277
async-fn-in-trait.md :: Caveats :: P:expected one of `!` or
async-join-parallel.md :: Good :: E0107
async-join-parallel.md :: Limiting Concurrency :: E0107
async-join-parallel.md :: When NOT to Use join! :: E0107
async-join-parallel.md :: futures::join_all for Dynamic Collections :: E0107,E0428
async-joinset-structured.md :: Abort on Drop :: E0069
async-select-racing.md :: Racing Multiple of Same Type :: E0107
async-spawn-blocking.md :: What Counts as Blocking :: P:expected one of `!`, `.`,
async-tokio-fs.md :: Good :: E0107
async-tokio-fs.md :: When std::fs is Acceptable :: E0428
async-tokio-runtime.md :: Good :: E0428
async-try-join.md :: Cancellation Behavior :: E0107
async-try-join.md :: Error Handling Patterns :: E0107
async-try-join.md :: Good :: E0107
async-try-join.md :: With Timeout :: E0107
async-watch-latest.md :: Configuration Reload Pattern :: E0308,E0369
doc-link-types.md :: Linking to Trait Items :: E0046
doc-question-mark.md :: Doctest Wrapper Pattern :: P:expected item after doc comment
err-anyhow-app.md :: Main Function Pattern :: E0428
err-context-chain.md :: Building Context Chains :: E0107
err-expect-bugs-only.md :: expect() Message Guidelines :: P:expected expression, found `.`
err-from-impl.md :: Blanket From Implementations :: P:non-item in item list
err-from-impl.md :: From with Context :: E0428
err-lowercase-msg.md :: Rust Standard Library Convention :: P:expected `;`, found `"connection refused"`,P:expected `;`, found `"invalid digit,P:expected `;`, found `"invalid utf-8,P:expected `;`, found `"permission denied"`
err-lowercase-msg.md :: When to Use Capitals :: P:expected statement after outer attribute
err-question-mark.md :: Good :: E0428
err-question-mark.md :: In main() :: E0428
err-result-over-panic.md :: When Panic IS Appropriate :: E0428
lint-deny-correctness.md :: Important Correctness Lints :: P:this file contains an unclosed
lint-deny-correctness.md :: Setup :: P:expected item, found `[`
lint-unsafe-doc.md :: Good :: E0106
lint-unsafe-doc.md :: Unchecked Operations :: E0424
lint-warn-complexity.md :: Examples :: E0428
lint-warn-complexity.md :: Overly Verbose Code :: P:expected `;`, found keyword `let`
lint-warn-complexity.md :: Unnecessary Complexity :: E0308
lint-warn-perf.md :: Collection Inefficiencies :: P:expected `;`, found keyword `let`
lint-warn-perf.md :: Examples :: E0428
lint-warn-perf.md :: Inefficient Operations :: P:expected `;`, found `iter`,P:expected `;`, found `s`,P:expected `;`, found keyword `if`
lint-warn-style.md :: Examples :: E0428
lint-warn-style.md :: Redundant Code :: P:expected `;`, found keyword `match`
mem-arrayvec.md :: When NOT to Use ArrayVec :: P:expected identifier, found `>`
mem-assert-type-size.md :: Good :: E0512
mem-assert-type-size.md :: When to Assert :: E0080
mem-avoid-format.md :: Pre-allocate for Multiple Appends :: E0428
mem-box-large-variant.md :: Recursive Types Require Boxing :: E0072,E0428
mem-clone-from.md :: How clone_from Works :: E0117
mem-compact-string.md :: Memory Comparison :: E0107
mem-compact-string.md :: When to Use :: E0428
mem-drop-order.md :: Controlling Drop Order for Locals :: P:expected one of `!` or
mem-reuse-collections.md :: Good :: E0107
name-acronym-word.md :: Standard Library Examples :: P:expected `;`, found `std`
name-funcs-snake.md :: Good :: P:expected item, found keyword `let`
name-into-ownership.md :: Standard Library Examples :: E0308
name-is-has-bool.md :: Standard Library Examples :: P:expected `;`, found `char`,P:expected `;`, found `iterator`,P:expected `;`, found `option`,P:expected `;`, found `path`,P:expected `;`, found `result`,P:expected `;`, found `str`
name-iter-convention.md :: Standard Library Examples :: P:expected `;`, found `map`,P:expected `;`, found `vec`
name-iter-type-match.md :: Custom Iterator Methods :: E0308,E0392
name-iter-type-match.md :: Standard Library Pattern :: E0116,E0117
name-lifetime-short.md :: Serde Convention :: P:cannot deserialize when there is
name-no-get-prefix.md :: Standard Library Examples :: P:expected `;`, found `btreemap`,P:expected `;`, found `hashmap`,P:expected `;`, found `option`,P:expected `;`, found `path`,P:expected `;`, found `result`,P:expected `;`, found `vec`
name-no-get-prefix.md :: When get_ IS Appropriate :: E0116
name-type-param-single.md :: Trait Bounds :: E0404,E0428,P:free function without a body
name-types-camel.md :: Good :: P:non-item in item list
opt-cache-friendly.md :: Avoid Pointer Chasing :: E0308
opt-inline-never-cold.md :: Pattern: Extract Cold Code :: E0428
own-clone-explicit.md :: When to Avoid Clone :: E0428
own-lifetime-elision.md :: Common Patterns :: P:expected one of `!`, `(`,
own-lifetime-elision.md :: The Three Elision Rules :: P:expected one of `!`, `(`,
own-lifetime-elision.md :: The Three Elision Rules :: P:expected one of `->`, `where`,
own-move-large.md :: Good :: E0599
own-refcell-interior.md :: Good :: E0599
own-slice-over-vec.md :: Path Types Too :: E0428
perf-chain-avoid.md :: When Chain Is Fine :: E0106
perf-extend-batch.md :: Good :: E0107
perf-extend-batch.md :: Pattern: Building Strings :: E0428
proj-feature-additive.md :: Good :: P:`#[panic_handler]` function required, but not,P:unwinding panics are not supported
proj-mod-rs-dir.md :: Consistency Rule :: P:expected `;`, found `mod_module_files`,P:expected one of `.`, `;`,
proj-pub-super-parent.md :: Good :: E0308
test-mock-traits.md :: Good :: E0046
type-enum-states.md :: Avoid Boolean Flags :: E0428
type-generic-bounds.md :: Bound Placement :: P:non-item in item list
type-generic-bounds.md :: Conditional Trait Implementation :: E0404
type-generic-bounds.md :: Good :: E0404
type-generic-bounds.md :: Implied Bounds :: E0404,E0428
type-generic-bounds.md :: Where Clause Benefits :: E0404,E0428
type-never-diverge.md :: Standard Library Examples :: P:expected one of `where` or
type-newtype-validated.md :: With Serde :: E0599
type-no-stringly.md :: Good :: E0599
type-phantom-marker.md :: Good :: E0308
type-repr-transparent.md :: FFI Pattern :: P:extern blocks must be unsafe
type-repr-transparent.md :: Good :: P:extern blocks must be unsafe
type-result-fallible.md :: The ? Operator :: E0428
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "ahash"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if",
"getrandom 0.3.4",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anyhow"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "bit-set"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bitflags"
version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
[[package]]
name = "bumpalo"
version = "3.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "bytes"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "castaway"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
dependencies = [
"rustversion",
]
[[package]]
name = "cc"
version = "1.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clap"
version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [
"anstyle",
"clap_lex",
]
[[package]]
name = "clap_lex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "compact_str"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rustversion",
"ryu",
"static_assertions",
]
[[package]]
name = "console"
version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87"
dependencies = [
"encode_unicode",
"libc",
"windows-sys",
]
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "downcast"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
[[package]]
name = "either"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
[[package]]
name = "encode_unicode"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "fragile"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9"
dependencies = [
"futures-core",
]
[[package]]
name = "futures"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-executor"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]]
name = "futures-macro"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]]
name = "futures-task"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"slab",
]
[[package]]
name = "generator"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3b854b0e584ead1a33f18b2fcad7cf7be18b3875c78816b753639aa501513ae"
dependencies = [
"cc",
"cfg-if",
"libc",
"log",
"rustversion",
"windows-link",
"windows-result",
]
[[package]]
name = "getrandom"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"libc",
"r-efi 5.3.0",
"wasip2",
]
[[package]]
name = "getrandom"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"libc",
"r-efi 6.0.0",
"wasip2",
"wasip3",
]
[[package]]
name = "half"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
dependencies = [
"cfg-if",
"crunchy",
"zerocopy",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"foldhash",
]
[[package]]
name = "hashbrown"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "id-arena"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "indexmap"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
[[package]]
name = "insta"
version = "1.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0f8fee8c926415c58d6ae43a08523a26faccb2323f5e6b644fe7dd4ef6b82"
dependencies = [
"console",
"once_cell",
"similar",
"tempfile",
]
[[package]]
name = "is-terminal"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
dependencies = [
"cfg-if",
"futures-util",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "leb128fmt"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
[[package]]
name = "loom"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
dependencies = [
"cfg-if",
"generator",
"scoped-tls",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "matchers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata",
]
[[package]]
name = "memchr"
version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
[[package]]
name = "mio"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "mockall"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2"
dependencies = [
"cfg-if",
"downcast",
"fragile",
"mockall_derive",
"predicates",
"predicates-tree",
]
[[package]]
name = "mockall_derive"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898"
dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "oorandom"
version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-link",
]
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "plotters"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
[[package]]
name = "plotters-svg"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
dependencies = [
"plotters-backend",
]
[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
[[package]]
name = "predicates"
version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe"
dependencies = [
"anstyle",
"predicates-core",
]
[[package]]
name = "predicates-core"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144"
[[package]]
name = "predicates-tree"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2"
dependencies = [
"predicates-core",
"termtree",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "proptest"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744"
dependencies = [
"bit-set",
"bit-vec",
"bitflags",
"num-traits",
"rand",
"rand_chacha",
"rand_xorshift",
"regex-syntax",
"rusty-fork",
"tempfile",
"unarray",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "r-efi"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
dependencies = [
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
dependencies = [
"getrandom 0.3.4",
]
[[package]]
name = "rand_xorshift"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
dependencies = [
"rand_core",
]
[[package]]
name = "rayon"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "rust-skills-checks"
version = "0.0.0"
dependencies = [
"ahash",
"anyhow",
"arrayvec",
"bumpalo",
"bytes",
"compact_str",
"criterion",
"futures",
"indexmap",
"insta",
"log",
"loom",
"memchr",
"mockall",
"once_cell",
"parking_lot",
"proc-macro2",
"proptest",
"quote",
"rayon",
"rustc-hash",
"secrecy",
"serde",
"serde_json",
"smallvec",
"smartstring",
"static_assertions",
"syn",
"tempfile",
"thin-vec",
"thiserror",
"tokio",
"tokio-util",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "rustc-hash"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
[[package]]
name = "rustix"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "rusty-fork"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
dependencies = [
"fnv",
"quick-error",
"tempfile",
"wait-timeout",
]
[[package]]
name = "ryu"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "secrecy"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
dependencies = [
"zeroize",
]
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "signal-hook-registry"
version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
"errno",
"libc",
]
[[package]]
name = "similar"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
[[package]]
name = "slab"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]]
name = "smartstring"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
dependencies = [
"autocfg",
"static_assertions",
"version_check",
]
[[package]]
name = "socket2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
"getrandom 0.4.2",
"once_cell",
"rustix",
"windows-sys",
]
[[package]]
name = "termtree"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
[[package]]
name = "thin-vec"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0f7e269b48f0a7dd0146680fa24b50cc67fc0373f086a5b2f99bd084639b482"
[[package]]
name = "thiserror"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "tokio"
version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
dependencies = [
"bytes",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio-util"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
dependencies = [
"bytes",
"futures-core",
"futures-io",
"futures-sink",
"futures-util",
"hashbrown 0.15.5",
"pin-project-lite",
"slab",
"tokio",
]
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex-automata",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unarray"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wait-timeout"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
dependencies = [
"libc",
]
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.4+wasi-0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
dependencies = [
"wit-bindgen 0.57.1",
]
[[package]]
name = "wasip3"
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen 0.51.0",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-encoder"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
dependencies = [
"leb128fmt",
"wasmparser",
]
[[package]]
name = "wasm-metadata"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
"indexmap",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags",
"hashbrown 0.15.5",
"indexmap",
"semver",
]
[[package]]
name = "web-sys"
version = "0.3.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
dependencies = [
"anyhow",
"heck",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [
"anyhow",
"heck",
"indexmap",
"prettyplease",
"syn",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
dependencies = [
"anyhow",
"prettyplease",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
[[package]]
name = "wit-component"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser",
]
[[package]]
name = "zerocopy"
version = "0.8.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zeroize"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[package]
name = "rust-skills-checks"
version = "0.0.0"
edition = "2024"
publish = false
# Harness for compile-checking the ```rust examples in ../rules/*.md.
# Each candidate block is generated into examples/ and type-checked with
# `cargo check --examples`. Not part of the published skill.
[lib]
path = "src/lib.rs"
[dependencies]
tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7", features = ["full"] }
futures = "0.3"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
anyhow = "1"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
log = "0.4"
smallvec = "1"
arrayvec = "0.7"
thin-vec = "0.2"
bytes = "1"
compact_str = "0.9"
smartstring = "1"
once_cell = "1"
parking_lot = "0.12"
rayon = "1"
rustc-hash = "2"
ahash = "0.8"
secrecy = "0.10"
memchr = "2"
static_assertions = "1"
bumpalo = "3"
indexmap = "2"
tempfile = "3"
mockall = "0.13"
proptest = "1"
insta = "1"
criterion = "0.5"
loom = "0.7"
syn = { version = "2", features = ["full", "extra-traits", "derive"] }
quote = "1"
proc-macro2 = "1"
[profile.dev]
debug = false
#!/usr/bin/env bash
# One command that reproduces CI locally. Run from anywhere:
#
# bash checks/check.sh
#
# It runs the exact same gates CI runs, pinned to the same toolchain
# (checks/rust-toolchain.toml -> Rust 1.95.0) and the same compile target
# (x86_64-unknown-linux-gnu), so a green run here means a green run on CI.
# On non-x86 hosts (e.g. Apple Silicon) the examples are cross-checked for that
# target — `cargo check` type-checks without linking, so no cross-linker needed.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TARGET="x86_64-unknown-linux-gnu"
echo "==> structure, links, and index parity"
python3 "$ROOT/checks/validate.py"
python3 "$ROOT/checks/gen_index.py" --check
echo "==> generating example files from rules"
cd "$ROOT/checks"
python3 gen.py
echo "==> compile-checking examples (target: $TARGET)"
# cargo exits non-zero on the intentional fragment snippets; the baseline gate
# below is what decides pass/fail.
cargo check --examples --target "$TARGET" --keep-going --message-format=json \
> check.json 2> check.err || true
echo "==> gating against the baseline"
python3 analyze.py check.json --check-baseline baseline.txt
echo "All checks passed."
#!/usr/bin/env python3
"""Generate SKILL.md's priority table + Quick Reference from rules/ and README counts.
Single source of truth: each rule file's `# id` header, its `> summary` line, and
the ordered CATEGORIES config below (prefix -> title + impact). Rule order within a
category is preserved from the current SKILL.md and any new rules are appended.
python3 checks/gen_index.py rewrite SKILL.md + README counts
python3 checks/gen_index.py --check exit 1 if they are out of date (CI)
"""
import re, sys, pathlib
HERE = pathlib.Path(__file__).resolve().parent
ROOT = HERE.parent
RULES = ROOT / "rules"
SKILL = ROOT / "SKILL.md"
README = ROOT / "README.md"
# (prefix, title, impact) in display order
CATEGORIES = [
("own-", "Ownership & Borrowing", "CRITICAL"),
("err-", "Error Handling", "CRITICAL"),
("mem-", "Memory Optimization", "CRITICAL"),
("unsafe-", "Unsafe Code", "CRITICAL"),
("api-", "API Design", "HIGH"),
("async-", "Async/Await", "HIGH"),
("conc-", "Concurrency", "HIGH"),
("opt-", "Compiler Optimization", "HIGH"),
("num-", "Numeric & Arithmetic Safety", "HIGH"),
("type-", "Type Safety", "MEDIUM"),
("trait-", "Trait & Generics Design", "MEDIUM"),
("conv-", "Conversions", "MEDIUM"),
("const-", "Const & Compile-Time", "MEDIUM"),
("serde-", "Serde", "MEDIUM"),
("pat-", "Pattern Matching", "MEDIUM"),
("macro-", "Macros", "MEDIUM"),
("closure-","Closures", "MEDIUM"),
("coll-", "Collections", "MEDIUM"),
("name-", "Naming Conventions", "MEDIUM"),
("test-", "Testing", "MEDIUM"),
("doc-", "Documentation", "MEDIUM"),
("obs-", "Observability", "MEDIUM"),
("perf-", "Performance Patterns", "MEDIUM"),
("proj-", "Project Structure", "LOW"),
("lint-", "Clippy & Linting", "LOW"),
("anti-", "Anti-patterns", "REFERENCE"),
]
def prefix_of(rule_id):
return rule_id.split("-", 1)[0] + "-"
def summary_of(path):
for line in path.read_text(encoding="utf-8").splitlines():
if line.startswith("> "):
return line[2:].strip()
raise SystemExit(f"{path.name}: no '> summary' line")
def build():
ids = sorted(p.stem for p in RULES.glob("*.md"))
by_prefix = {}
for rid in ids:
by_prefix.setdefault(prefix_of(rid), []).append(rid)
known = {p for p, _, _ in CATEGORIES}
stray = sorted(set(by_prefix) - known)
if stray:
raise SystemExit(f"rules with unknown prefix (add to CATEGORIES): {stray}")
# preserve existing Quick Reference order; append new rules (sorted)
existing = []
seen = set()
for m in re.finditer(r'rules/([a-z0-9-]+)\.md', SKILL.read_text(encoding="utf-8")):
if m.group(1) not in seen:
seen.add(m.group(1)); existing.append(m.group(1))
table_rows, qr_sections = [], []
total = 0
for i, (prefix, title, impact) in enumerate(CATEGORIES, 1):
rules = by_prefix.get(prefix, [])
ordered = [r for r in existing if r in rules] + sorted(r for r in rules if r not in existing)
total += len(ordered)
table_rows.append(f"| {i} | {title} | {impact} | `{prefix}` | {len(ordered)} |")
lines = [f"### {i}. {title} ({impact})", ""]
for rid in ordered:
lines.append(f"- [`{rid}`](rules/{rid}.md) - {summary_of(RULES / f'{rid}.md')}")
qr_sections.append("\n".join(lines))
table = ("| Priority | Category | Impact | Prefix | Rules |\n"
"|----------|----------|--------|--------|-------|\n"
+ "\n".join(table_rows))
quickref = "\n\n".join(qr_sections)
return table, quickref, total, len(CATEGORIES)
def render_skill(text, table, quickref, total, ncat):
text = re.sub(r"(## Rule Categories by Priority\n\n).*?(\n\n---\n\n## Quick Reference)",
lambda m: m.group(1) + table + m.group(2), text, flags=re.S)
text = re.sub(r"(## Quick Reference\n\n).*?(\n\n---\n\n## Recommended Cargo\.toml Settings)",
lambda m: m.group(1) + quickref + m.group(2), text, flags=re.S)
text = re.sub(r"\d+ rules across \d+ categories", f"{total} rules across {ncat} categories", text)
return text
def render_readme(text, total, ncat):
text = re.sub(r"rules-\d+", f"rules-{total}", text)
text = re.sub(r"categories-\d+", f"categories-{ncat}", text)
text = re.sub(r"\d+ Rust rules", f"{total} Rust rules", text)
text = re.sub(r"\d+ rules split into \d+ categories", f"{total} rules split into {ncat} categories", text)
return text
def main():
table, quickref, total, ncat = build()
skill_new = render_skill(SKILL.read_text(encoding="utf-8"), table, quickref, total, ncat)
readme_new = render_readme(README.read_text(encoding="utf-8"), total, ncat)
if "--check" in sys.argv:
stale = []
if skill_new != SKILL.read_text(encoding="utf-8"): stale.append("SKILL.md")
if readme_new != README.read_text(encoding="utf-8"): stale.append("README.md")
if stale:
print(f"OUT OF DATE: {', '.join(stale)} — run `python3 checks/gen_index.py`")
sys.exit(1)
print(f"OK: index up to date ({total} rules, {ncat} categories)")
return
SKILL.write_text(skill_new, encoding="utf-8")
README.write_text(readme_new, encoding="utf-8")
print(f"wrote index: {total} rules across {ncat} categories")
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Extract ```rust blocks from ../rules/*.md into cargo examples for compile checking.
Each candidate block becomes examples/<name>.rs. Blocks that are intentionally
non-compiling or unresolvable are skipped:
- under a "## Bad" section (anti-patterns, often deliberately wrong)
- nightly feature gates (#![feature ...])
- procedural-macro code (needs a proc-macro crate)
- placeholder crate names (my_crate, mycrate, mylib, ...)
- bare pseudocode ellipses (a line that is exactly `...`)
Fragments (snippets that reference undefined domain symbols) are still emitted;
the analyzer separates "only-resolution-errors" (fragments) from real bugs.
"""
import re, json, pathlib
HERE = pathlib.Path(__file__).resolve().parent
RULES = (HERE.parent / "rules").resolve()
OUT = HERE / "examples"
OUT.mkdir(exist_ok=True)
for f in OUT.glob("*.rs"):
f.unlink()
placeholder = re.compile(r'\b(my_crate|mycrate|mylib|my_app|my_project|my_lib|mycrate_derive)\b')
placeholder_use = re.compile(r'\buse\s+(model|transport|service|internal|app|domain)\b')
HEADER = ("#![allow(unused, dead_code, unreachable_code, unused_imports, "
"unused_variables, unused_mut, unused_assignments, unused_macros, "
"non_local_definitions)]\n")
def is_candidate(block: str, section: str) -> bool:
if section.strip().lower() == "bad":
return False
if "#![feature" in block:
return False
if "proc_macro" in block:
return False
if placeholder.search(block) or placeholder_use.search(block):
return False
for ln in block.splitlines():
if ln.strip() == "...":
return False
return True
manifest = {}
idx = 0
for md in sorted(RULES.glob("*.md")):
lines = md.read_text(encoding="utf-8").splitlines()
section = ""
i = 0
while i < len(lines):
line = lines[i]
m = re.match(r'^#{2,}\s+(.*)', line)
if m:
section = m.group(1).strip()
if line.strip() == "```rust":
start = i + 1
j = start
while j < len(lines) and lines[j].strip() != "```":
j += 1
block = "\n".join(lines[start:j])
if is_candidate(block, section):
name = f"{md.stem.replace('-', '_')}__{idx}"
has_main = re.search(r'\bfn\s+main\s*\(', block) is not None
has_inner_attr = "#![" in block
# A block that defines a module is item-level: compile it at the
# crate root so `mod m { use super::* }` resolves correctly.
has_mod = re.search(r'(?m)^\s*(pub(\([^)]*\))?\s+)?mod\s+\w', block) is not None
if has_main:
content = HEADER + block + "\n"
elif has_inner_attr or has_mod:
content = HEADER + block + "\nfn main() {}\n"
else:
content = (HEADER +
"async fn __ex() -> Result<(), Box<dyn std::error::Error>> {\n" +
block + "\n;\nOk(())\n}\nfn main() {}\n")
(OUT / f"{name}.rs").write_text(content, encoding="utf-8")
manifest[name] = {"file": md.name, "line": start + 1, "section": section}
idx += 1
i = j
i += 1
(HERE / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
print(f"generated {len(manifest)} example files (scanned {idx} rust blocks)")
checks — compile-verify the rule examples
A dev tool that type-checks the `rust code blocks in ../rules/*.md so the "Good" examples we tell agents to write actually compile. Not part of the published skill.
Run
# structural / link / index checks (no toolchain needed)
python3 checks/validate.py
# compile-check the examples
cd checks
python3 gen.py # extract blocks -> examples/
cargo check --examples --keep-going --message-format=json > check.json
python3 analyze.py check.json # classify results
python3 analyze.py check.json --check-baseline baseline.txt # CI gate: fail on NEW suspectsBoth run in CI (.github/workflows/ci.yml): validate (Python only) and examples (pinned to Rust 1.95.0, the toolchain baseline.txt was generated on).
Updating the baseline
baseline.txt lists the currently-accepted suspects (fragments/pseudocode the heuristics can't auto-classify). The CI gate fails only on signatures not in it. After intentionally adding/changing examples, regenerate it on the pinned toolchain and review the diff:
rustup run 1.95.0 cargo check --examples --keep-going --message-format=json > check.json
python3 analyze.py check.json --emit-baseline > baseline.txtWhen bumping the pinned toolchain in ci.yml, regenerate baseline.txt on the same version in the same commit.
How it works
gen.py extracts each candidate block into examples/<name>.rs, wrapping fragments in an async fn -> Result<...> so ? and .await type-check. It skips blocks that can't compile standalone by design: ## Bad anti-patterns, nightly #![feature] gates, procedural-macro code, placeholder crate names (my_crate, …), and bare ... pseudocode.
analyze.py buckets each failing example by compiler error code:
- fragment — every error is name resolution (undefined symbol/crate). These
reference helpers defined elsewhere in the rule; expected, ignored.
- artifact — caused by extraction (a
&selfmethod body wrapped as a free
fn, pseudocode .../??? tokens, dangling doc comments). Not real bugs.
- low — only "type annotations needed"; compiles in the rule's real context.
- SUSPECT — anything else (type mismatch, no-method, bad syntax, wrong
arity, missing trait impl). These are the ones to review and fix.
Notes
- Run on Rust ≥ 1.95: some examples use APIs stabilized in 1.95 (e.g. the
MaybeUninit array From conversions) and will spuriously fail on older toolchains.
- Generated files (
examples/,*.json,manifest.json,target/) are
gitignored; only the source (gen.py, analyze.py, Cargo.toml) is tracked.
# Pins the toolchain and target for the compile-check harness so local runs
# match CI exactly. Any `cargo` invocation in this directory uses this.
[toolchain]
channel = "1.95.0"
targets = ["x86_64-unknown-linux-gnu"]
// Empty harness crate. Examples under examples/ are generated from
// ../rules/*.md by gen.py and type-checked with `cargo check --examples`.
#!/usr/bin/env python3
"""Structural / link / index validation for the rule library.
Checks (no Rust toolchain needed):
- every rules/<id>.md starts with `# <id>` matching its filename
- has a `> ` one-line summary near the top
- has `## Why It Matters` and `## See Also`
- every `](other.md)` link resolves to an existing rule file
- SKILL.md links exactly the set of files in rules/ (no broken links, no orphans)
Exits non-zero (and prints every problem) if anything fails.
"""
import re, pathlib, sys
HERE = pathlib.Path(__file__).resolve().parent
ROOT = HERE.parent
RULES = ROOT / "rules"
SKILL = ROOT / "SKILL.md"
errors = []
def err(msg): errors.append(msg)
rule_files = sorted(RULES.glob("*.md"))
rule_names = {p.name for p in rule_files}
link_re = re.compile(r'\]\((?:\./)?([a-z0-9-]+\.md)\)')
for p in rule_files:
text = p.read_text(encoding="utf-8")
lines = text.splitlines()
head = lines[0].strip() if lines else ""
if head != f"# {p.stem}":
err(f"{p.name}: first line is {head!r}, expected '# {p.stem}'")
if not any(l.startswith("> ") for l in lines[:6]):
err(f"{p.name}: missing '> ' summary line near the top")
for section in ("## Why It Matters", "## See Also"):
if section not in text:
err(f"{p.name}: missing '{section}' section")
for tgt in link_re.findall(text):
if tgt not in rule_names:
err(f"{p.name}: broken link -> {tgt}")
# SKILL.md index parity
skill = SKILL.read_text(encoding="utf-8")
linked = set(re.findall(r'rules/([a-z0-9-]+\.md)', skill))
for tgt in sorted(linked):
if tgt not in rule_names:
err(f"SKILL.md: links missing file rules/{tgt}")
for name in sorted(rule_names):
if name not in linked:
err(f"SKILL.md: rule rules/{name} is not listed in the index")
if errors:
print(f"VALIDATION FAILED ({len(errors)} problem(s)):\n")
for e in errors:
print(f" - {e}")
sys.exit(1)
print(f"OK: {len(rule_files)} rules valid; index lists all {len(linked)} of them.")
SKILL.md
Contributing
Thanks for helping improve rust-skills! This repo is a set of focused Rust best-practice rules consumed by AI coding agents. Contributions usually mean adding a rule, improving an existing one, or fixing an example.
Adding or editing a rule
1. Create `rules/<prefix>-<name>.md` with a kebab-case id that starts with an existing category prefix (own-, err-, mem-, unsafe-, api-, async-, conc-, opt-, num-, type-, trait-, conv-, const-, serde-, pat-, macro-, closure-, coll-, name-, test-, doc-, obs-, perf-, proj-, lint-, anti-). To propose a brand-new category, add it to CATEGORIES in checks/gen_index.py.
2. Follow the format of existing rules exactly:
````markdown
prefix-rule-name
One-line imperative summary.
Why It Matters
Two to four sentences.
Bad
// the anti-patternGood
// the recommended patternSee Also
- other-rule - why it's related
````
The first line must be # <id> (matching the filename), followed by a > summary line. ## Why It Matters and ## See Also are required; See Also links must point to real rule files.
3. Make examples compile on current stable Rust (2024 edition). Prefer self-contained ## Good examples (define the types you reference) so the compile harness can verify them. Keep error/log message strings lowercase with no trailing punctuation.
4. Regenerate the index so SKILL.md and the README counts stay in sync — never hand-edit the generated table or Quick Reference:
python3 checks/gen_index.py5. Add a `CHANGELOG.md` entry under the next version.
Before opening a PR
Run the same checks CI runs:
# structure, links, index parity, and that SKILL.md/README are up to date
python3 checks/validate.py
python3 checks/gen_index.py --check
# compile-check the examples (Rust >= 1.95)
cd checks
python3 gen.py
cargo check --examples --keep-going --message-format=json > check.json
python3 analyze.py check.json --check-baseline baseline.txtIf the compile gate reports a real bug, fix the example. If you intentionally added a new fragment-style snippet, refresh the baseline (see checks/README.md).
Style
- Be concrete and example-driven, not preachy.
- Cite sources by name (the Rust Reference, the API Guidelines, a crate) rather
than fragile deep links.
- Keep rules small and single-purpose; cross-link related rules in
See Also.
MIT License
Copyright (c) 2025 Leonardo Maldonado
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Rust Skills
265 Rust rules your AI coding agent can use to write better code. Current for Rust 1.96 (2024 edition).
Works with Claude Code, Cursor, Windsurf, Copilot, Codex, Aider, Zed, Amp, Cline, and pretty much any other agent that supports skills.
Why
Out of the box, coding agents write average Rust — they clone to dodge the borrow checker, .unwrap() everything, and reach for Box<dyn Trait> when impl Trait would do. These rules encode what expert Rust actually looks like: idiomatic, fast, and safe. Each rule is small and focused, so the agent pulls in only what's relevant to the code in front of it.
Install
npx add-skill leonardomso/rust-skillsThat's it. The CLI figures out which agents you have and installs the skill to the right place.
How to use it
After installing, just ask your agent:
/rust-skills review this function/rust-skills is my error handling idiomatic?/rust-skills check for memory issues/rust-skills is this unsafe block sound?The agent loads the relevant rules and applies them to your code.
See it in action
Ask the agent to review a function like this:
// before
fn first_word(s: &String) -> String {
s.clone().split_whitespace().next().unwrap().to_string()
}With these rules loaded, it knows to take &str instead of &String, drop the needless clone() and allocation, and return an Option instead of panicking:
// after — applies own-slice-over-vec, own-borrow-over-clone, anti-unwrap-abuse
fn first_word(s: &str) -> Option<&str> {
s.split_whitespace().next()
}What's in here
265 rules split into 26 categories:
| Category | Rules | What it covers |
|---|---|---|
| Ownership & Borrowing | 12 | When to borrow vs clone, Arc/Rc, lifetimes |
| Error Handling | 12 | thiserror for libs, anyhow for apps, the ? operator |
| Memory | 17 | SmallVec, arenas, avoiding allocations, mem::take, drop order |
| Unsafe Code | 7 | SAFETY: comments, Miri, MaybeUninit, 2024-edition unsafe |
| API Design | 17 | Builder pattern, newtypes, sealed traits, FromIterator |
| Async | 18 | Tokio patterns, channels, async fn in traits, cancel safety |
| Concurrency | 4 | rayon, scoped threads, atomic ordering, thread-locals |
| Optimization | 12 | LTO, inlining, PGO, SIMD |
| Numeric & Arithmetic | 5 | Overflow handling, as vs TryFrom, float compare, NonZero |
| Type Safety | 13 | Newtypes, parse don't validate, Deref, Display/Debug |
| Trait & Generics Design | 6 | dyn vs generic, associated types, blanket impls, object safety, orphan rule |
| Conversions | 3 | TryFrom, FromStr, AsMut |
| Const & Compile-Time | 4 | const fn, const vs static, const generics, const {} blocks |
| Serde | 8 | rename_all, default, flatten, enum tagging, validate-on-deserialize |
| Pattern Matching | 5 | let-else, matches!, if-let chains, exhaustive matches |
| Macros | 8 | macro_rules! hygiene, fragment specifiers, proc-macros with syn/quote |
| Closures | 5 | Fn/FnMut/FnOnce bounds, returning impl Fn, move & disjoint capture |
| Collections | 4 | HashMap/BTreeMap/IndexMap, Vec/VecDeque, sets, BinaryHeap |
| Naming | 16 | Following Rust API Guidelines |
| Testing | 15 | Proptest, mockall, criterion, loom, snapshot tests |
| Docs | 12 | Doc examples, intra-doc links, README/crate-doc unification |
| Observability | 7 | tracing over log, spans, structured fields, redacting secrets |
| Performance | 13 | Iterators, entry API, faster hashers, I/O buffering |
| Project Structure | 14 | Workspaces, module layout, features, MSRV |
| Linting | 13 | Clippy config, CI setup, unexpected_cfgs |
| Anti-patterns | 15 | Common mistakes and how to fix them |
Each rule has:
- Why it matters
- A bad code example
- A good code example
- Links to related rules and sources
How it works
The design is built for low token cost and easy auditing:
- [`SKILL.md`](./SKILL.md) is a lightweight index — every rule listed as a one-line summary, grouped by category, with a link to its file. The agent reads this first.
- [`rules/`](./rules) holds one Markdown file per rule (
<prefix>-<name>.md). The agent opens only the handful relevant to your code instead of loading all 218 — progressive disclosure keeps context small. - Prefixes (
own-,err-,unsafe-,async-, …) map directly to categories, so an agent reviewing async code can pull justasync-,conc-, andown-rules.
CLAUDE.md and AGENTS.md are symlinks to SKILL.md, so the same content works across agent conventions.
Manual install
If add-skill doesn't work for your setup, here's how to install manually:
<details> <summary><b>Claude Code</b></summary>
Global (applies to all projects):
git clone https://github.com/leonardomso/rust-skills.git ~/.claude/skills/rust-skillsOr just for one project:
git clone https://github.com/leonardomso/rust-skills.git .claude/skills/rust-skills</details>
<details> <summary><b>OpenCode</b></summary>
git clone https://github.com/leonardomso/rust-skills.git .opencode/skills/rust-skills</details>
<details> <summary><b>Cursor</b></summary>
git clone https://github.com/leonardomso/rust-skills.git .cursor/skills/rust-skillsOr just grab the skill file:
curl -o .cursorrules https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
<details> <summary><b>Windsurf</b></summary>
mkdir -p .windsurf/rules
curl -o .windsurf/rules/rust-skills.md https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
<details> <summary><b>OpenAI Codex</b></summary>
git clone https://github.com/leonardomso/rust-skills.git .codex/skills/rust-skillsOr use the AGENTS.md standard:
curl -o AGENTS.md https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
<details> <summary><b>GitHub Copilot</b></summary>
mkdir -p .github
curl -o .github/copilot-instructions.md https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
<details> <summary><b>Aider</b></summary>
Add to .aider.conf.yml:
read: path/to/rust-skills/SKILL.mdOr pass it directly:
aider --read path/to/rust-skills/SKILL.md</details>
<details> <summary><b>Zed</b></summary>
curl -o AGENTS.md https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
<details> <summary><b>Amp</b></summary>
git clone https://github.com/leonardomso/rust-skills.git .agents/skills/rust-skills</details>
<details> <summary><b>Cline / Roo Code</b></summary>
mkdir -p .clinerules
curl -o .clinerules/rust-skills.md https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
<details> <summary><b>Other agents (AGENTS.md)</b></summary>
If your agent supports the AGENTS.md standard:
curl -o AGENTS.md https://raw.githubusercontent.com/leonardomso/rust-skills/master/SKILL.md</details>
All rules
See SKILL.md for the full list with links to each rule file.
Sources & attribution
These rules are an independent synthesis of official Rust guidance, well-known books, and patterns drawn from widely-used open-source crates. They are not affiliated with or endorsed by the Rust project or any crate author. The text and code examples are original summaries — no substantial content is copied from the sources below.
Official Rust documentation
- The Rust Reference
- Rust API Guidelines
- The Rustonomicon (unsafe code)
- Rust 2024 Edition Guide
- The Cargo Book
- Standard library docs and release notes
Books & guides
- The Rust Performance Book — Nicholas Nethercote
- Rust Design Patterns — rust-unofficial
- Rust Atomics and Locks — Mara Bos
- Effective Rust — David Drysdale
Tooling
Real-world codebases studied for idioms
- ripgrep, tokio, serde, clap, polars, axum, cargo, hyper, bevy, rayon, and dtolnay's crates (thiserror, anyhow, syn)
This project is MIT-licensed. Referenced upstream materials remain under their own licenses — the official Rust documentation and API Guidelines are dual MIT / Apache-2.0.
Contributing
PRs welcome. To add or change a rule:
1. Create rules/<prefix>-<name>.md using a kebab-case id with an existing category prefix (own-, err-, mem-, …). 2. Follow the format of existing rules: a > one-line summary, then ## Why It Matters, ## Bad, ## Good, and ## See Also (with links that resolve). 3. Make sure code examples compile on current stable Rust. 4. Add the rule to the index in SKILL.md (Quick Reference list + the category count) so it stays in sync.
````markdown
prefix-rule-name
One-line imperative summary.
Why It Matters
Two to four sentences.
Bad
// the anti-patternGood
// the recommended patternSee Also
- other-rule - why it's related
````
License
MIT
Related skills
How it compares
Use rust-skills for comprehensive 179-rule Rust idioms during generation and review; narrower Rust skills suit single-topic fixes like clippy lints only.
FAQ
How are rules organized?
Twenty-six categories sorted by impact from ownership and errors through anti-patterns.
Library versus app errors?
Use thiserror for libraries and anyhow for application error handling per err rules.
When add explicit lifetimes?
Rely on elision first; add lifetimes only when the compiler requires them.
Is Rust Skills safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.