PluginBench
Skill
Pass
Audit score 90

m15-anti-pattern

actionbook/rust-skills

Identify and refactor Rust code anti-patterns during review.

What is m15-anti-pattern?

This skill helps you spot common Rust anti-patterns—like excessive cloning, unwrap in production, and fighting the borrow checker—and understand why they're problematic. Use it when reviewing code to diagnose design issues and suggest idiomatic alternatives.

  • Recognize 8+ common anti-patterns (clone everywhere, unwrap in production, Rc misuse, unsafe for convenience, OOP via Deref, giant match arms, String overuse, ignored #[must_use])
  • Distinguish between symptom and root cause (e.g., cloning indicates ownership design issues)
  • Map anti-patterns to upstream design skills (m09-domain, m01-ownership) and downstream implementation skills (m06-error-handling, m02-resource)
  • Provide quick refactoring guidance for each anti-pattern with concrete alternatives
  • Identify code smells and suggest structural improvements (extract methods, clarify data flow, add encapsulation)

How to install m15-anti-pattern

npx skills add https://github.com/actionbook/rust-skills --skill m15-anti-pattern
Claude Code
Cursor
Windsurf
Cline

How to use m15-anti-pattern

  1. 1.When reviewing code, check the Quick Review Checklist for common issues
  2. 2.If you spot suspicious code, ask: Is this solving the symptom or the cause?
  3. 3.Use the Anti-Pattern → Better Pattern table to identify the issue and find the idiomatic alternative
  4. 4.Trace up to design skills (m09-domain, m01-ownership) if the root cause is architectural
  5. 5.Trace down to implementation skills (m06-error-handling, m02-resource) for concrete fixes

Use cases

Good for
  • Review a colleague's code and spot why they're cloning everywhere, then trace back to ownership design
  • Encounter unwrap() in production code and recommend proper error handling with ? or expect()
  • See index-based loops and suggest iterator-based alternatives
  • Identify String used where &str or Cow<str> would be more efficient
  • Spot fighting-the-borrow-checker patterns and suggest data structure restructuring
Who it's for
  • Rust code reviewers
  • Developers learning idiomatic Rust patterns
  • Team leads establishing code quality standards
  • Developers refactoring legacy Rust code

m15-anti-pattern FAQ

How do I know if code is an anti-pattern or just a valid choice?

Ask: Is this solving the symptom or the cause? If you're cloning to avoid borrow-checker errors, that's a symptom of unclear ownership (anti-pattern). If you're cloning a large struct once for performance reasons, that may be justified.

What's the difference between this skill and m01-ownership?

m01-ownership teaches reference patterns and ownership rules. This skill identifies when code violates those patterns and suggests fixes. Use m01 to learn, use this to review.

Should I always avoid .unwrap()?

In library code, yes—propagate errors with ?. In binaries, unwrap is acceptable for truly unreachable cases, but prefer expect() with a message explaining why it can't fail.

How do I fix 'fighting the borrow checker'?

It usually means your data structure doesn't match your ownership model. Restructure to own data outright, use references consistently, or consider Rc/Arc if shared ownership is needed.

When is .clone() acceptable?

When the cost is justified (e.g., cloning a small struct once) or when ownership semantics require it. If you're cloning to escape borrow-checker errors, restructure instead.

Full instructions (SKILL.md)

Source of truth, from actionbook/rust-skills.


name: m15-anti-pattern description: "Use when reviewing code for anti-patterns. Keywords: anti-pattern, common mistake, pitfall, code smell, bad practice, code review, is this an anti-pattern, better way to do this, common mistake to avoid, why is this bad, idiomatic way, beginner mistake, fighting borrow checker, clone everywhere, unwrap in production, should I refactor, 反模式, 常见错误, 代码异味, 最佳实践, 地道写法" user-invocable: false

Anti-Patterns

Layer 2: Design Choices

Core Question

Is this pattern hiding a design problem?

When reviewing code:

  • Is this solving the symptom or the cause?
  • Is there a more idiomatic approach?
  • Does this fight or flow with Rust?

Anti-Pattern → Better Pattern

Anti-PatternWhy BadBetter
.clone() everywhereHides ownership issuesProper references or ownership
.unwrap() in productionRuntime panics?, expect, or handling
Rc when single ownerUnnecessary overheadSimple ownership
unsafe for convenienceUB riskFind safe pattern
OOP via DerefMisleading APIComposition, traits
Giant match armsUnmaintainableExtract to methods
String everywhereAllocation waste&str, Cow<str>
Ignoring #[must_use]Lost errorsHandle or let _ =

Thinking Prompt

When seeing suspicious code:

  1. Is this symptom or cause?

    • Clone to avoid borrow? → Ownership design issue
    • Unwrap "because it won't fail"? → Unhandled case
  2. What would idiomatic code look like?

    • References instead of clones
    • Iterators instead of index loops
    • Pattern matching instead of flags
  3. Does this fight Rust?

    • Fighting borrow checker → restructure
    • Excessive unsafe → find safe pattern

Trace Up ↑

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-PatternTrace ToQuestion
Clone everywherem01-ownershipWho should own this data?
Unwrap everywherem06-error-handlingWhat's the error strategy?
Rc everywherem09-domainIs ownership clear?
Fighting lifetimesm09-domainShould data structure change?

Trace Down ↓

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

Top 5 Beginner Mistakes

RankMistakeFix
1Clone to escape borrow checkerUse references
2Unwrap in productionPropagate with ?
3String for everythingUse &str
4Index loopsUse iterators
5Fighting lifetimesRestructure to own data

Code Smell → Refactoring

SmellIndicatesRefactoring
Many .clone()Ownership unclearClarify data flow
Many .unwrap()Error handling missingAdd proper handling
Many pub fieldsEncapsulation brokenPrivate + accessors
Deep nestingComplex logicExtract methods
Long functionsMultiple responsibilitiesSplit
Giant enumsMissing abstractionTrait + types

Common Error Patterns

ErrorAnti-Pattern CauseFix
E0382 use after moveCloning vs ownershipProper references
Panic in productionUnwrap everywhere?, matching
Slow performanceString for all text&str, Cow
Borrow checker fightsWrong structureRestructure
Memory bloatRc/Arc everywhereSimple ownership

Deprecated → Better

DeprecatedBetter
Index-based loops.iter(), .enumerate()
collect::<Vec<_>>() then iterateChain iterators
Manual unsafe cellCell, RefCell
mem::transmute for castsas or TryFrom
Custom linked listVec, VecDeque
lazy_static!std::sync::OnceLock

Quick Review Checklist

  • No .clone() without justification
  • No .unwrap() in library code
  • No pub fields with invariants
  • No index loops when iterator works
  • No String where &str suffices
  • No ignored #[must_use] warnings
  • No unsafe without SAFETY comment
  • No giant functions (>50 lines)

Related Skills

WhenSee
Ownership patternsm01-ownership
Error handlingm06-error-handling
Mental modelsm14-mental-model
Performancem10-performance