dot_claude/skills/rust-expert/SKILL.md
Use when needing idiomatic, high-performance Rust (Edition 2024, 1.93+) guidance for systems logic, async services, or performance-critical libraries.
npx skillsauth add nijaru/dotfiles rust-expertInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
edition = "2024" in Cargo.toml. Migrate with cargo fix --edition.&str/&[T]/&T over owned types at API boundaries. .clone() to fix borrow errors is a code smell — rethink ownership.thiserror for libraries (typed errors), anyhow for applications (context-rich chains). Never Box<dyn Error> in library APIs.tokio for network I/O, rayon for CPU-parallel work, sync stdlib for file I/O (async file I/O rarely improves throughput).String/i32 for domain concepts. Parse at boundaries, use types internally..unwrap() in library code — use ?, expect("reason"), or proper error handling.Box<dyn Error> in library return types — use thiserror enums.super:: paths — use crate:: (clearer, refactor-stable).pub use re-exports unless intentionally part of the public API surface.lazy_static! or global OnceLock/Mutex state — pass context explicitly.unsafe block without a // SAFETY: comment explaining the invariants.extern "C" blocks — use unsafe extern "C" (Edition 2024 requirement).Captures<> trick for RPIT lifetimes — use use<'a, T> precise capturing or rely on 2024 defaults.std::sync::Mutex for high-contention paths — prefer parking_lot::Mutex or restructure with channels.#[bench] attribute — hard error since 1.88; use criterion or divan.impl Trait in return position now captures all in-scope lifetimes by default. Use impl Trait + use<'a, T> (stable 1.82) to restrict explicitly.
// 2024: captures 'a implicitly — may require use<> to be more restrictive
fn iter<'a>(&'a self) -> impl Iterator<Item = &str> { ... }
fn iter<'a>(&'a self) -> impl Iterator<Item = &str> + use<'a> { ... } // explicit
unsafe extern blocks: All extern blocks with unsafe items now require unsafe extern "ABI" {}.unsafe_op_in_unsafe_fn: Unsafe operations inside unsafe fn require their own unsafe {} block — functions declare preconditions, blocks discharge them.gen is reserved: Cannot be used as an identifier (reserved for future generator syntax).let chains (1.88, Edition 2024): Mix let bindings and boolean guards freely.
if let Some(x) = map.get(&key) && x.is_valid() && let Some(y) = x.child() { ... }
async || { ... } stable — use instead of || async { ... } when you need AsyncFn bounds.&dyn Derived coerces to &dyn Base — no manual wrapper needed.
fn needs_base(x: &dyn Base) { ... }
needs_base(derived_ref); // works in 1.86+
impl Trait + use<'a, T> specifies exactly which params the opaque type may use. Prefer over + '_ outlives trick.#[target_feature] on safe fns (1.86): Safe functions can now be annotated — call sites still require unsafe if calling without the feature active.std::arch intrinsics or std::simd (portable SIMD, still nightly). Target-specific: enable with #[target_feature(enable = "avx2")] on safe functions.a.strict_add(b), strict_mul, etc. — panics on overflow in all build modes. Use for invariant enforcement without checked_* verbosity.a.carrying_add(b, carry), borrowing_sub — for multi-precision arithmetic without inline assembly.hint::select_unpredictable (1.87): Timing-safe conditional selection — avoids branch predictor speculation, useful in crypto code.slice.as_chunks::<N>() returns (&[[T; N]], &[T]) — exact-size chunks without bounds checks in the loop.MaybeUninit slices (1.93): uninit_slice.write_copy_of_slice(&src) and assume_init_ref() for safe incremental initialization.let (reader, writer) = io::pipe()? — pairs with std::process::Command for subprocess I/O without threads.file.lock(), file.try_lock_shared(), file.unlock() — cross-platform advisory locks.Duration helpers (1.90): Duration::from_mins(5), Duration::from_hours(2).path.file_prefix() (stem without all extensions), buf.add_extension("gz") (appends without replacing).thiserror: derive Error with #[error("...")] and #[from] for automatic From impls.anyhow: .context("what you were doing") on every ? at call sites. Use anyhow::bail! and ensure! macros.cargo nextest — parallel, faster, better output than cargo test.cargo clippy --all-features --all-targets -- -D warnings in CI.cargo deny check for license/security/duplicate dep policy.cargo machete to find unused dependencies.cargo miri test before any unsafe PR.criterion (mature, HTML reports) or divan (simpler setup). Never #[bench].cargo fix --edition && cargo fix --edition-idioms then review diff.development
Use after completing a bug fix, feature, refactor, or tk task when the first implementation taught enough context to replace it with a simpler, cleaner, or more coherent version before finalizing.
development
Use when writing, migrating, or reviewing Zig code across recent stable versions (0.14-0.16), especially to correct stale syntax or stdlib, build.zig, allocator, formatting, or runtime API knowledge.
documentation
Use when reviewing or revising text (prose, docs, commits) to remove AI patterns and improve voice/clarity.
content-media
Use when fetching X/Twitter post content by URL, or searching for recent X posts.