From rust-skills
Detects Rust anti-patterns like excessive clones, unwraps in production, Rc/unsafe misuse, and giant match arms. Suggests idiomatic fixes, traces to ownership/design issues.
npx claudepluginhub actionbook/rust-skills --plugin rust-skillsThis skill uses the workspace's default tool permissions.
> **Layer 2: Design Choices**
Reviews Rust code for ownership, borrowing, lifetimes, error handling, trait design, unsafe usage, and common mistakes in .rs files. Covers 2021 edition idioms and borrow checker issues.
Guides writing and reviewing idiomatic Rust code covering ownership patterns, error handling, performance optimization, testing, linting with Clippy, and Cargo tooling.
Guides Rust best practices, common patterns, and idiomatic code including borrowing, error propagation, iterators, and design patterns like builder and newtype.
Share bugs, ideas, or general feedback.
Layer 2: Design Choices
Is this pattern hiding a design problem?
When reviewing code:
| Anti-Pattern | Why Bad | Better |
|---|---|---|
.clone() everywhere | Hides ownership issues | Proper references or ownership |
.unwrap() in production | Runtime panics | ?, expect, or handling |
Rc when single owner | Unnecessary overhead | Simple ownership |
unsafe for convenience | UB risk | Find safe pattern |
OOP via Deref | Misleading API | Composition, traits |
| Giant match arms | Unmaintainable | Extract to methods |
String everywhere | Allocation waste | &str, Cow<str> |
Ignoring #[must_use] | Lost errors | Handle or let _ = |
When seeing suspicious code:
Is this symptom or cause?
What would idiomatic code look like?
Does this fight Rust?
To design understanding:
"Why does my code have so many clones?"
↑ Ask: Is the ownership model correct?
↑ Check: m09-domain (data flow design)
↑ Check: m01-ownership (reference patterns)
| Anti-Pattern | Trace To | Question |
|---|---|---|
| Clone everywhere | m01-ownership | Who should own this data? |
| Unwrap everywhere | m06-error-handling | What's the error strategy? |
| Rc everywhere | m09-domain | Is ownership clear? |
| Fighting lifetimes | m09-domain | Should data structure change? |
To implementation (Layer 1):
"Replace clone with proper ownership"
↓ m01-ownership: Reference patterns
↓ m02-resource: Smart pointer if needed
"Replace unwrap with proper handling"
↓ m06-error-handling: ? operator
↓ m06-error-handling: expect with message
| Rank | Mistake | Fix |
|---|---|---|
| 1 | Clone to escape borrow checker | Use references |
| 2 | Unwrap in production | Propagate with ? |
| 3 | String for everything | Use &str |
| 4 | Index loops | Use iterators |
| 5 | Fighting lifetimes | Restructure to own data |
| Smell | Indicates | Refactoring |
|---|---|---|
Many .clone() | Ownership unclear | Clarify data flow |
Many .unwrap() | Error handling missing | Add proper handling |
Many pub fields | Encapsulation broken | Private + accessors |
| Deep nesting | Complex logic | Extract methods |
| Long functions | Multiple responsibilities | Split |
| Giant enums | Missing abstraction | Trait + types |
| Error | Anti-Pattern Cause | Fix |
|---|---|---|
| E0382 use after move | Cloning vs ownership | Proper references |
| Panic in production | Unwrap everywhere | ?, matching |
| Slow performance | String for all text | &str, Cow |
| Borrow checker fights | Wrong structure | Restructure |
| Memory bloat | Rc/Arc everywhere | Simple ownership |
| Deprecated | Better |
|---|---|
| Index-based loops | .iter(), .enumerate() |
collect::<Vec<_>>() then iterate | Chain iterators |
| Manual unsafe cell | Cell, RefCell |
mem::transmute for casts | as or TryFrom |
| Custom linked list | Vec, VecDeque |
lazy_static! | std::sync::OnceLock |
.clone() without justification.unwrap() in library codepub fields with invariantsString where &str suffices#[must_use] warningsunsafe without SAFETY comment| When | See |
|---|---|
| Ownership patterns | m01-ownership |
| Error handling | m06-error-handling |
| Mental models | m14-mental-model |
| Performance | m10-performance |