PluginBench
Skill
Pass
Audit score 90

m03-mutability

actionbook/rust-skills

Resolve Rust mutability conflicts by understanding ownership, borrowing rules, and interior mutability patterns.

What is m03-mutability?

Addresses E0596, E0499, E0502 and related borrow-checker errors. Use this skill when you encounter mutability conflicts, need to decide between &mut, Cell, RefCell, Mutex, or RwLock, or when borrow conflicts suggest a data-structure redesign.

  • Diagnose mutability errors (E0596, E0499, E0502) and trace root causes
  • Choose appropriate interior mutability pattern (Cell, RefCell, Mutex, RwLock, Atomic) based on thread context and data type
  • Restructure code to satisfy borrow rules without unnecessary runtime overhead
  • Identify when borrow conflicts signal deeper design issues in data structures
  • Evaluate trade-offs between compile-time (&mut) and runtime (RefCell) borrow checking

How to install m03-mutability

npx skills add https://github.com/actionbook/rust-skills --skill m03-mutability
Claude Code
Cursor
Windsurf
Cline

How to use m03-mutability

  1. 1.Identify the specific mutability error (E0596, E0499, E0502, or RefCell panic)
  2. 2.Ask the core question: Why does this data need to change, and who should control mutation?
  3. 3.Determine thread context: single-threaded or multi-threaded
  4. 4.Select the appropriate pattern from the decision table (Cell, RefCell, Mutex, RwLock, or Atomic)
  5. 5.If borrow conflicts persist, trace up to m09-domain to evaluate data-structure design

Use cases

Good for
  • Fixing 'cannot borrow as mutable' errors by selecting the right mutability mechanism
  • Resolving multiple-borrow conflicts by restructuring ownership or using interior mutability
  • Choosing between Cell and RefCell for single-threaded mutable state
  • Selecting Mutex vs RwLock for thread-safe shared mutation based on read/write patterns
  • Detecting when RefCell panics indicate a need for data-structure redesign rather than error handling
Who it's for
  • Rust developers encountering borrow-checker errors
  • Engineers designing shared mutable state in single-threaded or concurrent code
  • Teams refactoring code to reduce borrow conflicts

m03-mutability FAQ

When should I use Cell vs RefCell?

Use Cell<T> for Copy types with zero runtime cost; use RefCell<T> for non-Copy types that need runtime borrow checking. Both are single-threaded only.

What's the difference between Mutex and RwLock?

Mutex allows one writer at a time; RwLock allows multiple concurrent readers or one writer. Use RwLock when reads vastly outnumber writes.

Why does RefCell panic at runtime instead of failing at compile time?

RefCell defers borrow checking to runtime, allowing interior mutability through &self. Panics indicate a logic error; consider restructuring instead of just handling the panic.

How do I know if a borrow conflict means my data structure is wrong?

If conflicts persist after trying different borrow patterns, check m09-domain: the data may need to be split into separate fields or types with clearer ownership.

Is it safe to use Mutex in an async context?

No; use async-aware locks (tokio::sync::Mutex) instead. Regular Mutex can block executor threads. See m07-concurrency for details.

Full instructions (SKILL.md)

Source of truth, from actionbook/rust-skills.


name: m03-mutability description: "CRITICAL: Use for mutability issues. Triggers: E0596, E0499, E0502, cannot borrow as mutable, already borrowed as immutable, mut, &mut, interior mutability, Cell, RefCell, Mutex, RwLock, 可变性, 内部可变性, 借用冲突" user-invocable: false

Mutability

Layer 1: Language Mechanics

Core Question

Why does this data need to change, and who can change it?

Before adding interior mutability, understand:

  • Is mutation essential or accidental complexity?
  • Who should control mutation?
  • Is the mutation pattern safe?

Error → Design Question

ErrorDon't Just SayAsk Instead
E0596"Add mut"Should this really be mutable?
E0499"Split borrows"Is the data structure right?
E0502"Separate scopes"Why do we need both borrows?
RefCell panic"Use try_borrow"Is runtime check appropriate?

Thinking Prompt

Before adding mutability:

  1. Is mutation necessary?

    • Maybe transform → return new value
    • Maybe builder → construct immutably
  2. Who controls mutation?

    • External caller → &mut T
    • Internal logic → interior mutability
    • Concurrent access → synchronized mutability
  3. What's the thread context?

    • Single-thread → Cell/RefCell
    • Multi-thread → Mutex/RwLock/Atomic

Trace Up ↑

When mutability conflicts persist:

E0499/E0502 (borrow conflicts)
    ↑ Ask: Is the data structure designed correctly?
    ↑ Check: m09-domain (should data be split?)
    ↑ Check: m07-concurrency (is async involved?)
Persistent ErrorTrace ToQuestion
Repeated borrow conflictsm09-domainShould data be restructured?
RefCell in asyncm07-concurrencyIs Send/Sync needed?
Mutex deadlocksm07-concurrencyIs the lock design right?

Trace Down ↓

From design to implementation:

"Need mutable access from &self"
    ↓ T: Copy → Cell<T>
    ↓ T: !Copy → RefCell<T>

"Need thread-safe mutation"
    ↓ Simple counters → AtomicXxx
    ↓ Complex data → Mutex<T> or RwLock<T>

"Need shared mutable state"
    ↓ Single-thread: Rc<RefCell<T>>
    ↓ Multi-thread: Arc<Mutex<T>>

Borrow Rules

At any time, you can have EITHER:
├─ Multiple &T (immutable borrows)
└─ OR one &mut T (mutable borrow)

Never both simultaneously.

Quick Reference

PatternThread-SafeRuntime CostUse When
&mut TN/AZeroExclusive mutable access
Cell<T>NoZeroCopy types, no refs needed
RefCell<T>NoRuntime checkNon-Copy, need runtime borrow
Mutex<T>YesLock contentionThread-safe mutation
RwLock<T>YesLock contentionMany readers, few writers
Atomic*YesMinimalSimple types (bool, usize)

Error Code Reference

ErrorCauseQuick Fix
E0596Borrowing immutable as mutableAdd mut or redesign
E0499Multiple mutable borrowsRestructure code flow
E0502&mut while & existsSeparate borrow scopes

Interior Mutability Decision

ScenarioChoose
T: Copy, single-threadCell<T>
T: !Copy, single-threadRefCell<T>
T: Copy, multi-threadAtomicXxx
T: !Copy, multi-threadMutex<T> or RwLock<T>
Read-heavy, multi-threadRwLock<T>
Simple flags/countersAtomicBool, AtomicUsize

Anti-Patterns

Anti-PatternWhy BadBetter
RefCell everywhereRuntime panicsClear ownership design
Mutex for single-threadUnnecessary overheadRefCell
Ignore RefCell panicHard to debugHandle or restructure
Lock inside hot loopPerformance killerBatch operations

Related Skills

WhenSee
Smart pointer choicem02-resource
Thread safetym07-concurrency
Data structure designm09-domain
Anti-patternsm15-anti-pattern