Receber por email
← Voltar para o catálogo

rust-expert

This skill should be used when the user is writing, reviewing, debugging, or architecting Rust code. Detects edition and toolchain from the project. Provides expert critique covering ownership, error handling, unsafe review, async correctness, trait design, type system patterns, performance, SOLID principles, and Cargo/workspace practices. Use when the user asks "critique my Rust code", "review th

11estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add johnkozaris/jko-claude-plugins

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/rust-expert/svg)](https://www.skillteca.com.br/skills/rust-expert)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

This skill guides expert Rust development. Detect the project's edition and toolchain from Cargo.toml (edition, rust-version) and adapt guidance accordingly. Every finding explains WHY it matters — what bug it prevents, what production incident it avoids, what design problem it reveals. Do not invent APIs — verify any method or type exists in stable Rust before suggesting it.

How to Think About Rust Problems

Before fixing any issue, trace through the layers:

  • Layer 3 — Domain (WHY): Business rules, performance constraints, deployment context. These constrain everything below.
  • Layer 2 — Design (WHAT): Error strategy, type design, API surface, module structure. Check against SOLID and API Guidelines.
  • Layer 1 — Mechanics (HOW): Compiler errors, ownership, lifetimes, trait bounds. Fix the immediate issue, but always trace UP.

When a compiler error appears, reframe it as a design question:

| Error | Don't Just Say | Ask Instead | | -------------------------------- | ---------------- | -------------------------------------- | | E0382 (value moved) | "Clone it" | Who should own this data? | | E0597 (doesn't live long enough) | "Add a lifetime" | Is the scope boundary correct? | | E0277 (trait not satisfied) | "Add the bound" | Is this the right abstraction? | | E0499 (two mutable borrows) | "Use RefCell" | Should this be two separate resources? | | "future is not Send" | "Wrap in Arc" | Does this state need to cross threads? |

Ownership & Borrowing

→ _Consult [ownership reference](references/ownership.md) for borrowing rules, Cow, smart pointers._

DO: Default to borrowing (&T). Move to owned only when the callee must store the value. DO: Use &str and &[T] in function parameters — not &String or &Vec<T>. DO: Use Cow<'_, str> when a function conditionally allocates. DO: Treat Arc::clone(&handle) of service handles, DB pools, and channels as idiomatic — that is what M-SERVICES-CLONE is for. DON'T: Clone owned heap data (Vec, String, large structs) to silence the borrow checker — restructure ownership instead. DON'T: Over-annotate lifetimes — elision covers 95% of cases. DON'T: Write &'a mut self on methods — borrows self for its entire lifetime.

Error Handling

→ _Consult [error-handling reference](references/error-handling.md) for thiserror/anyhow/snafu decision matrix._

DO: Use ? with .context() at every propagation point. DO: Use thiserror (v2) for libraries, anyhow (v2) for applications. DO: Use #[non_exhaustive] on public error enums. DO: Use .expect("invariant X holds because Y") to assert what the type system cannot express — invariant assertion is fine; lazy error handling is not. DON'T: Use .unwrap() or .expect() on Results from outside the program (parse, IO, env, deserialize, network) — this is what took down Cloudflare on Nov 18, 2025: a hard-coded 200-feature limit hit unexpected input, .unwrap() on the Err panicked in fl2_worker_thread, 5xx globally for hours. DON'T: Implement From for fallible conversions — use TryFrom. DON'T: Both log AND propagate an error — pick one.

Type Design

→ _Consult [type-patterns reference](references/type-patterns.md) for newtype, typestate, builder patterns._

DO: Parse, don't validate — convert raw inputs into types that carry their validity. DO: Replace boolean parameters with enums — process(data, true, false) is unreadable. DO: Use #[must_use] on functions returning values callers must handle. DON'T: Use ..Default::default() — silently wrong when fields are added. DON'T: Use catch-all _ in match on owned enums — swallows new variants.

Design Principles

→ _Consult [design-principles reference](references/design-principles.md) for SOLID, Microsoft M-_ rules, modern Rust table.\*

DO: Apply Single Responsibility — one struct per concept, one domain per module. DO: Depend on traits, not concrete types (Dependency Inversion). DO: Use #[expect(lint)] instead of #[allow(lint)] (warns when stale, Rust 1.81+). DON'T: Use weasel word names — BookingService, DataManager. Name types after what they ARE. DON'T: Expose Arc, Rc, Box in public API signatures — hide implementation details.

Traits & API Surface

→ _Consult [traits reference](references/traits.md) for generics vs dyn, standard traits, sealed patterns._

DO: Implement standard traits eagerly (Debug, Clone, PartialEq, Hash, Default). DO: Default to generics. Use dyn Trait only for genuine runtime polymorphism. DON'T: Violate Hash/Eq consistency — the most dangerous silent bug in Rust's stdlib.

Async

→ _Consult [async reference](references/async.md) for blocking taxonomy, cancellation safety, JoinSet._

DO: Keep business logic synchronous. Use async only at I/O boundaries. DO: Use CancellationToken for graceful shutdown — not task.abort(). DON'T: Block async threads for more than 10-100 microseconds between .await points. DON'T: Hold a MutexGuard across .await — drop it first. DON'T: Make every function async "just in case" — async infects signatures upward.

Concurrency

→ _Consult [concurrency reference](references/concurrency.md) for decision tree, actor pattern, channels, atomic orderings._

DO: Ask first: "Do I actually need concurrency?" If no measured bottleneck, stay sequential. DO: Pick the primitive by access pattern — see Concurrency Pattern Triage below. DO: Use bounded channels in production for backpressure. DON'T: Default to Arc<Mutex<T>> for everything — it's the right tool for short critical sections, not for global app state. DON'T: Use async for CPU-bound work — use Rayon or spawn_blocking.

When to reach for which concurrency primitive

Pick by access pattern, not reflex. Channels (tokio::sync::mpsc for async, crossbeam-channel for sync) for ownership transfer between tasks. The actor pattern (one task owns state, handle wraps an mpsc::Sender<Msg>) for long-lived stateful concurrent components — this replaces most uses of Arc<Mutex<BigStruct>>. Arc<Mutex<T>> for short critical sections on shared data; std::sync::Mutex became futex-based on Linux in 1.62 and the gap to parking_lot closed dramatically (parking_lot still has an edge under heavy contention), so reach for parking_lot only for its specific features (fairness, reentrant, RwLock downgrade, deadlock detection). Arc<RwLock<T>> for read-heavy with rare writes (watch for writer starvation). ArcSwap<T> for snapshot reload (lock-free reads, atomic swap). DashMap for partition-keyed concurrent access — never call another DashMap method while holding a Ref/RefMut to the same map, that's a shard self-deadlock. Atomics for single primitives, with the right ordering (Relaxed for independent counters, Release/Acquire for publishing data).

The anti-pattern is Arc<Mutex<WholeAppState>> as a god-object. Split by concern, let each piece pick its own primitive.

Unsafe

→ _Consult [unsafe reference](references/unsafe.md) for SAFETY comments, Miri, UB patterns._

DO: Every unsafe block needs a // SAFETY: comment explaining the invariant. DO: Run cargo +nightly miri test on code with unsafe. DO: Deny unsafe at crate level (unsafe_code = "deny") with surgical allows. DON'T: Use unsafe when safe alternatives exist — all memory-safety CVEs in Rust trace to unsafe code.

Performance

→ _Consult [performance reference](references/performance.md) for build config, allocation patterns, benchmarking._

DO: Profile before optimizing — cargo flamegraph, DHAT, samply. DO: Use overflow-checks = true in release profiles (CVE-2018-1000810). DO: Use strict_add

Compartilhar X LinkedIn