rust
/rust
Pomaga w konwencjach, idiomach i obsłudze błędów w Rust: współbieżność z wątkami i Tokio, cargo, clippy, rustfmt i rustdoc.
- Autor
- xobotyi ↗
- Repozytorium
- cc-foundry ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 26.10.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 12
- Skrypty
- 0
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 0
Brak sygnałów. Repozytorium zmienione 26.10.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
Co robi i kiedy
Pomaga w konwencjach, idiomach i obsłudze błędów w Rust: współbieżność z wątkami i Tokio, cargo, clippy, rustfmt i rustdoc.
Oryginalny opis (EN)
Rust language conventions, idioms, error handling, concurrency (CPU-bound parallelism with threads/rayon and I/O-bound async with Tokio), the cargo/clippy/rustfmt toolchain, and rustdoc. Invoke whenever task involves any interaction with Rust code — writing, reviewing, refactoring, debugging, or understanding .rs files and Cargo projects.
Jak działa
- Route to Reference
- Naming
- Ownership and Borrowing
- Error Handling
- Traits and Generics
- Iterators and Pattern Matching
- Concurrency: Choose the Right Model First
- Project Structure
- Toolchain Gates
- Doc Comments
Podgląd SKILL.md
---
name: rust
description: >-
Rust language conventions, idioms, error handling, concurrency (CPU-bound parallelism with
threads/rayon and I/O-bound async with Tokio), the cargo/clippy/rustfmt toolchain, and rustdoc.
Invoke whenever task involves any interaction with Rust code — writing, reviewing, refactoring,
debugging, or understanding .rs files and Cargo projects.
---
# Rust
Lean on the type system and the borrow checker. They are the design surface, not an obstacle. When the compiler rejects
code, the ownership model is wrong — restructure who owns and who borrows rather than reaching for `.clone()`, `Rc`, or
`unsafe` to silence it. Make illegal states unrepresentable: encode invariants in types so the wrong code fails to
compile instead of failing at runtime. A fight with the borrow checker is a design review the compiler is giving you for
free.
## Route to Reference
Read the reference before doing focused work in its area; SKILL.md alone is sufficient for routine code.
- **Idioms and ownership patterns** — `${CLAUDE_SKILL_DIR}/references/idioms.md` borrowing/ownership restructuring,
`impl Trait` vs generics vs `dyn`, iterator adapters, `match`/`if let`/`let else`, newtype and builder patterns,
`From`/`Into`/`TryFrom`, the `as_`/`to_`/`into_` cost cheat-table
- **Error handling** — `${CLAUDE_SKILL_DIR}/references/errors.md` `Result`/`Option`/`?`, `thiserror` enum templates,
`anyhow` `.context()`, the panic/`unwrap`/`expect` policy, error-type design (`Display`/`Error`/`Send`/`Sync`)
- **Anti-patterns** — `${CLAUDE_SKILL_DIR}/references/anti-patterns.md` AI-produced anti-patterns mapped to the Clippy
lints that catch them, with the idiomatic fix for each
- **API design** — `${CLAUDE_SKILL_DIR}/references/api-guidelines.md` the Rust API Guidelines `C-*` checklist, RFC 430
naming, `#[non_exhaustive]`, `#[must_use]`, common-trait derives, sealed traits, builders
- **Parallelism** — `${CLAUDE_SKILL_DIR}/references/parallelism.md` threads, scoped threads, rayon, `Send`/`Sync`,
channels, shared state (`Arc`/`Mutex`) — the CPU-bound multicore path
- **Async** — `${CLAUDE_SKILL_DIR}/references/async.md` the `Future`/executor model, Tokio, the compiler-invisible
footgun checklist (blocking in async, holding `!Send` across `.await`), "do you even need async?"
- **Project structure** — `${CLAUDE_SKILL_DIR}/references/structure.md` `mod.rs`-free layout, cargo workspaces, the
`[lints]`/`[workspace.lints]` table, profiles, features, MSRV
- **Toolchain** — `${CLAUDE_SKILL_DIR}/references/toolchain.md` the fmt/clippy/nextest/deny verification gates,
rust-analyzer configuration, recommended compiler and Clippy lint sets
- **Edition 2024** — `${CLAUDE_SKILL_DIR}/references/edition-2024.md` Rust 2024 edition specifics and migration via
`cargo fix --edition`
- **Documentation** — `${CLAUDE_SKILL_DIR}/references/documentation.md` rustdoc conventions, doctests, `missing_docs`,
intra-doc links, semver-checks
## Naming
- Casing follows RFC 430: `UpperCamelCase` for types/traits/enum variants, `snake_case` for functions/methods/modules,
`SCREAMING_SNAKE_CASE` for consts/statics.
- Acronyms are one word in `UpperCamelCase` (`Uuid`, `Stdin`, not `UUID`, `StdIn`); lower-cased in `snake_case`.
- Getters omit the `get_` prefix: `fn first(&self) -> &First`, not `fn get_first`. Use `get` only when one obvious value
is gotten (e.g. `Cell::get`).
- Ad-hoc conversion methods signal cost through their prefix: `as_` = free borrow-to-borrow view; `to_` = expensive
(allocates or computes); `into_` = consuming, ownership transfer.
- Collection iterators are `iter` (`&T`), `iter_mut` (`&mut T`), `into_iter` (`T`); the iterator type name matches the
method (`into_iter` -> `IntoIter`).
- Names use consistent verb-object word order (`ParseAddrError`, matching `ParseIntError`). Drop weasel words —
`Manager`, `Service`, `Factory`, `Helper`, `Util` rarely belong in a type name; name the thing for what it is
(`Bookings`, not `BookingService`), append a quality only when it does something specific (`BookingDispatcher`).
- A `Builder` is Rust's name for a factory. Accept `impl Fn() -> Foo` rather than a `FooBuilder` parameter.
## Ownership and Borrowing
- Accept the least-owning type that does the job: `&str` over `&String`, `&[T]` over `&Vec<T>`, `&T` over `T` when not
consuming. Return owned values; borrow in parameters.
- Treat `.clone()` as a signal, not a fix. A clone to satisfy the borrow checker usually means lifetimes or ownership
are structured wrong — split the borrow, narrow the scope, or restructure who owns the data.
- Reach for `Rc`/`Arc` only for genuine shared ownership (a graph, a cache, a value with no single owner), not to dodge
a lifetime annotation.
- Prefer adjusting a function to take `&self`/`&T` over cloning at the call site. Borrow at the narrowest scope so a
mutable borrow ends before the next access begins (non-lexical lifetimes allow this).
- Use lifetime elision wherever it applies; write explicit lifetimes only when the compiler asks or when they document a
real relationship between inputs and outputs.
## Error Handling
- Functions that can fail return `Result<T, E>`; absence-not-error returns `Option<T>`. Propagate with `?`, do not
match-and-rewrap.
- Libraries define typed errors with `thiserror` (one enum, `#[error("...")]` per variant, `#[from]` for source
conversions). Applications use `anyhow::Result` and attach `.context(...)` at each layer.
- Error types implement `std::error::Error`, `Display`, `Debug`, and are `Send + Sync + 'static` so they cross threads
and compose with `anyhow`/`Box<dyn Error>`.
- `.unwrap()` and `.expect()` are permitted only on a provable invariant (with `.expect("why this cannot fail")`
documenting the proof), inside `const` contexts, or in tests. They are never error-propagation.
- A detected programming bug panics; it is not an `Error`. A panic means "stop the program" — never use panics to
communicate recoverable errors upstream, and never assume a panic will be caught. Genuinely fallible operations
(parsing, I/O, user input) return `Result`.
- Prefer making invalid states uncompilable over validating at runtime: a `NonEmptyVec` or a parsed `Email` newtype
beats a runtime check on a raw `Vec`/`String`.
## Traits and Generics
- Static dispatch is the default: generics (`fn f<T: Trait>`) or `impl Trait` in argument and return position.
Monomorphization keeps it allocation-free and inlinable.
- Use `dyn Trait` only for genuine runtime polymorphism — heterogeneous collections (`Vec<Box<dyn Draw>>`), plugin
boundaries, or breaking deep monomorphization. Always write `dyn` explicitly (`Box<dyn Error>`, `&dyn Handler`);
bare-trait-object syntax has been an error since edition 2021.
- `impl Trait` in argument position is shorthand for an anonymous generic; in return position it hides a concrete type.
Switch to a named generic when the caller must name the type or supply it via turbofish.
- Derive the common traits eagerly where they fit: `Debug` on every public type, plus `Clone`, `Copy`, `PartialEq`,
`Eq`, `Hash`, `PartialOrd`, `Ord`, `Default` as semantics allow. Implement `Display` for types meant to be read by
humans (errors, string-like wrappers).
- Implement conversions via the standard traits — `From` (which gives `Into` free), `TryFrom`, `AsRef`, `AsMut` — not
ad-hoc methods, so generic code and `?` interoperate.
## Iterators and Pattern Matching
- Express transformations as iterator adapter chains (`.iter().filter().map().collect()`), not manual index loops. They
are bounds-check-friendly, lazy, and clearer.
- Reach for `for x in &collection` over `for i in 0..collection.len()`; index only when the index itself is the data.
- `match` arms must be exhaustive — let the compiler enforce that every variant is handled rather than ending with a
catch-all `_` that silently swallows new variants.
- Use `if let` / `while let` for single-pattern matches, and `let ... else { return / continue / bail }` to bind-or-
bail in one line instead of nesting the happy path inside a `match`.
- Destructure in the pattern (function params, `let`, match arms) rather than reaching into fields by `.0`/`.field`
afterward.
## Concurrency: Choose the Right Model First
**Pick the concurrency model from the workload before writing any concurrent code — this decision is not
interchangeable:**
- **CPU-bound / multicore compute** (parsing, hashing, image processing, number crunching) -> OS threads or **rayon**
(`par_iter`). **Never reach for async here** — async provides zero parallel speedup for CPU work; it only interleaves
tasks at `.await` points on (often) a single logical flow.
- **Many concurrent I/O operations** (thousands of sockets, requests, file handles) -> **async / Tokio**. Async wins by
not blocking a thread while waiting on I/O, letting one runtime juggle huge numbers of in-flight operations.
- **A handful of blocking I/O tasks** -> plain threads are simpler than dragging in an async runtime; use async only
when the concurrency count makes a thread-per-task model wasteful.
Further rules once the model is chosen:
- Shared state crosses threads via `Arc<Mutex<T>>` / `Arc<RwLock<T>>`; immutable shared data via `Arc<T>`. Move work and
ownership across threads with channels (`std::sync::mpsc`, `crossbeam`, or `tokio::sync` in async).
- Public types should be `Send` (and usually `Sync`) so they work under Tokio and behind runtime abstractions. A `!Send`
value held across an `.await` makes the whole future `!Send` — keep `Rc`/`RefCell` out of async scopes that span an
await.
- Never block in async: no `std::thread::sleep`, no synchronous file/network I/O, no long CPU loops on the runtime.
Offload CPU work with `tokio::task::spawn_blocking` or a rayon pool, and use the runtime's async timers/IO.
- The borrow checker does not see deadlocks or blocking-in-async — those footguns are invisible at compile time. Read
`references/async.md` before writing async code.
## Project Structure
- Use the `mod.rs`-free layout: a module `foo` lives in `foo.rs`, its submodules in `foo/bar.rs`. Never create new
`mod.rs` files.
- Set all lint levels in the `[lints]` (or `[workspace.lints]`) table in `Cargo.toml`, not in scattered `#![deny(...)]`
attributes or `RUSTFLAGS`. This keeps lint policy in one auditable place and inherited across the workspace.
- Override a project-global lint at a narrow scope with `#[expect(lint, reason = "...")]`, not `#[allow]` — `expect`
warns when the lint stops firing, preventing stale overrides. (`#[allow]` is acceptable on generated code/macros.)
- Multi-crate projects use a cargo workspace with a shared `[workspace.lints]` and `[workspace.dependencies]`. Split a
crate when a submodule is independently useful — many small crates compile faster and prevent dependency cycles.
- Keep `unsafe` confined to the smallest possible module; soundness boundaries are module boundaries. Every `unsafe`
block carries a `// SAFETY:` comment justifying it. Never write sound-looking safe wrappers over unsound assumptions.
## Toolchain Gates
Code is not done until these pass (run via Bash, surfacing each command):
- `cargo fmt --check` — formatting is non-negotiable; never hand-format.
- `cargo clippy --all-targets --all-features -- -D warnings` — Clippy clean across the whole build graph, warnings as
errors. Fix the cause; suppress a lint only with a scoped `#[expect(..., reason = "...")]`.
- `cargo nextest run` **and** `cargo test --doc` — nextest is the fast test runner but does **not** execute doctests, so
the separate `--doc` run is mandatory to keep documentation examples honest.
- `cargo deny check` (or `cargo audit`) — gate dependencies for advisories, license, and source policy.
## Doc Comments
- `//!` documents the crate root and modules; `///` documents items (functions, types, fields, variants). Write docs as
part of the change, not after.
- Use the standard rustdoc sections: `# Examples`, `# Panics` (when the fn can panic), `# Errors` (what a `Result`
returns on failure), `# Safety` (the invariants a caller of an `unsafe` fn must uphold).
- Doctests use `?` for fallible calls (wrap the body so it returns `Result`), never `.unwrap()` — examples are also
documentation of idiomatic usage.
- Libraries enable `#![warn(missing_docs)]` so every public item is documented. Link related items with intra-doc links
(`[`Type`]`, `[`mod::func`]`).
- When you change an exported symbol's signature or behavior, update its doc comment in the same edit — a stale doc is
worse than none.
## Code Navigation (LSP Required)
A `rust-analyzer` LSP is configured for `.rs` files. For semantic navigation, use LSP tools — they understand types,
traits, and macro expansion in ways text search cannot:
- **goToDefinition** — jump to where a symbol is defined (through re-exports and macros).
- **findReferences** — every real use of a symbol, not textual name collisions.
- **hover** — resolved type, signature, and docs at a position.
- **workspaceSymbol** — locate a type/fn/trait by name across the workspace.
- **goToImplementation** — concrete implementors of a trait, or the trait a method satisfies.
- **incomingCalls / outgoingCalls** — call hierarchy for impact analysis before a change.
Use Grep/Glob only for non-semantic text: comments, string literals, config files, log messages, `Cargo.toml` entries.
Reaching for Grep to find a definition or all callers is a mistake when the LSP resolves it precisely.
## Integration
- **the-coder** owns the language-agnostic workflow — discovery, planning, verification loop. This skill governs
Rust-specific conventions only; defer the workflow mechanics to `the-coder` and apply these rules within it.
- **rust-testing** owns the test ecosystem (`#[test]`/integration/doctest layout, cargo-nextest, proptest, insta,
criterion, mockall, rstest). When writing or reviewing tests, that skill leads; it relies on this skill for general
language conventions and on `references/async.md` for async-test mechanics.
- When this skill's conventions conflict with an established pattern already pervasive in the codebase, the codebase
wins — follow it and flag the divergence once.
## Application
When **writing** Rust:
- Apply every convention above silently — do not narrate "per RFC 430 I'll name this...". Just write idiomatic code.
- Match the surrounding codebase. If it diverges from these conventions consistently (e.g. uses `mod.rs`, a different
error crate), follow the codebase and note the divergence once rather than fighting it file-by-file.
- Run the toolchain gates before declaring the work done.
When **reviewing** Rust:
- Cite the specific violation (file:line and the rule), then show the corrected code inline. Do not lecture in the
abstract.
- Prioritize correctness and soundness (unsound `unsafe`, blocking-in-async, panics-as-errors, data races) over style
nits; let `cargo fmt` and Clippy carry the mechanical issues.
- Confirm the concurrency model fits the workload (CPU-bound vs I/O-bound) before reviewing the concurrency details.
---
The borrow checker is a collaborator, not an adversary. When it pushes back, the answer is almost never `.clone()`,
`Rc`, or `unsafe` — it is a clearer ownership structure. Encode invariants in types so wrong code does not compile, keep
`unsafe` rare and justified, and let the toolchain gates (fmt, clippy, nextest + doctests, deny) be the final word on
done.
Pliki w paczce (12)
- SKILL.md 15 KB
- .dev/reference-inventory.json 3 KB
- references/anti-patterns.md 27 KB
- references/api-guidelines.md 28 KB
- references/async.md 17 KB
- references/documentation.md 24 KB
- references/edition-2024.md 17 KB
- references/errors.md 19 KB
- references/idioms.md 21 KB
- references/parallelism.md 20 KB
- references/structure.md 18 KB
- references/toolchain.md 15 KB
Wersje
| Repozytorium | Wynik | Licencja |
|---|---|---|
| Ta strona · xobotyi/cc-foundry | 100 | MIT |
| TerminalSkills/skills | 100 | Apache-2.0 |
| crbnos/carbon | 100 | AGPL-3.0 |
| nimadorostkar/Claude-Skills-collection | 100 | MIT |
| claude-dev-suite/claude-dev-suite | 100 | MIT |
| appwrite/claude-plugin | 100 | BSD-3-Clause |
| vinnie357/claude-skills | 100 | MIT |
| G1Joshi/Agent-Skills | 100 | MIT |
| heyAyushh/stacc | 100 | MIT |
Migawka bazy z 28.10.2026 · wersja paczki 3b211dcc61f1 (skrót SHA-256 całej paczki)
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100rust-development
Wspiera rozwój w Rust: cargo, clippy, rustfmt, async z Tokio, Serde i bezpieczeństwo pamięci. - 100rust-development
Obsługuje pełny toolchain Rust: cargo, rustfmt, clippy i kompilację do WASM, przy budowie, testach i błędach kompilacji. - 100rust-systems
Opisuje wzorce Rust dla narzędzi CLI, usług backendowych i kodu aplikacyjnego: workspace Cargo, usługi axum i tokio, CLI clap, współbieżność async oraz konfiguracja clippy, rustfmt i nextest. - 92rust-conventions
Podpowiada konwencje Rust: edycję, fmt i clippy, obsługę błędów, dokumentację unsafe, testy, tokio i cargo audit. - 95rust-quality-checker
Sprawdza jakość kodu Rust z rustfmt, clippy, cargo check i analizą bezpieczeństwa, pod kątem idiomatycznego kodu i dobrych praktyk. - 100writing-rust
Prowadzi idiomatyczne programowanie w Rust: Cargo, testy, rustfmt i clippy, z naciskiem na własność, błędy Result, małe API i testy zachowania.