diff options
Diffstat (limited to 'skills/exterminate-slop/references/languages/rust.md')
| -rw-r--r-- | skills/exterminate-slop/references/languages/rust.md | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/skills/exterminate-slop/references/languages/rust.md b/skills/exterminate-slop/references/languages/rust.md new file mode 100644 index 0000000..89717ce --- /dev/null +++ b/skills/exterminate-slop/references/languages/rust.md @@ -0,0 +1,33 @@ +# Rust + +Use this note for Rust source scopes. It sharpens the generic extermination pass; it is not a style guide. + +## Manifest + +Source files are `*.rs` under the requested subtree. Exclude generated, vendored, target, fixture, snapshot, and build-output files unless the user explicitly includes them. Include tests when they encode domain shape, duplicated construction, or behavior-preservation evidence. + +## Navigation + +Use `rust_analyzer` aggressively. Anchor from live use sites before jumping through declarations: field access, constructor call, enum match, trait method call, conversion site, parser call, or repeated builder/update path. Use references and rename feasibility to understand whether an abstraction can be moved mechanically. Text search is for manifesting and cross-checking; semantic navigation is for decisions. + +## Deslopping Moves + +Prefer type-level compression over local explanation. If a primitive carries semantics, replace it with a domain type: newtype, enum, value object, typestate, phase-specific struct, trait, generic, const-generic shape, or smart constructor. Closed string worlds become enums. Validated identifiers and tokens become opaque wrappers. Tuple packs and repeated field bundles become named domain objects. Repeated `Option`/`bool` combinations become state types that make invalid states unrepresentable. + +Treat DRY as stronger than YAGNI. Repeated parse, validate, normalize, render, patch, convert, query, or error-shaping logic should collapse into one owner. Prefer `From`/`TryFrom`, dedicated constructors, extension traits, local algebra, iterator transforms, and small modules with a clear semantic center. Macros are legitimate when they enforce uniformity, remove boilerplate, or keep hot code compact. + +Bias toward code volume reduction when it increases semantic density. Delete dead compatibility shims, redundant wrappers, ceremonial intermediates, repeated guards made obsolete by types, and "simple" structs that only scatter one concept across context. Overabstraction is not a crime; weak abstraction is. A powerful abstraction is acceptable when it compresses a real invariant or repeated skeleton. + +## Rust-Specific Suspects + +Scrutinize `String`, `&str`, `PathBuf`, raw integers, bool flags, public tuple returns, builder structs full of `Option`, enums mirrored by strings, repeated `match` skeletons, repeated `clone`/conversion glue, parallel vectors/maps, and hand-rolled state machines encoded as primitive fields. + +Scrutinize generic transport boundaries separately. Serialization, database rows, CLI args, wire protocols, and FFI may need primitive shapes externally, but the primitive must be quarantined at the boundary and converted into domain types immediately. + +## Verification + +After edits, run `cargo fmt` and the narrowest meaningful Rust checks for the touched crates, then widen if the abstraction crosses crate boundaries. Prefer existing project commands. Use Clippy when it is part of the repo contract, but never treat Clippy as a substitute for the extermination ledger. + +## Avoid + +Do not write Rust like Python with types. Do not preserve public API compatibility unless requested. Do not add abstraction whose name is foggy or whose invariant is imaginary. Do not reject a correct abstraction merely because it looks advanced. Do not leave five concrete repetitions because one generic/macro/trait solution feels "less readable." |