
M03 Mutability
Resolve Rust borrow and mutability errors (E0596, E0499, E0502) by choosing the right mutability model instead of fighting the compiler.
Overview
m03-mutability is an agent skill most often used in Build (also Ship testing) that guides Rust mutability and interior mutability decisions when borrow checker errors block compilation.
Install
npx skills add https://github.com/actionbook/rust-skills --skill m03-mutabilityWhat is this skill?
- Error-to-design-question table for E0596, E0499, E0502, and RefCell panics
- Three-step thinking prompt: necessity, who controls mutation, thread context
- Interior mutability map: Cell/RefCell single-thread vs Mutex/RwLock/Atomic multi-thread
- Trace-up guidance when borrow conflicts imply wrong data structure
- Layer 1 language mechanics framing—mutability as a design decision not a quick mut fix
- Covers errors E0596, E0499, E0502 and RefCell panic scenarios
Adoption & trust: 948 installs on skills.sh; 1.2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
The compiler rejects your borrows with E0596/E0499/E0502 and you are unsure whether to add mut, split borrows, or redesign shared state.
Who is it for?
Indie Rust authors debugging real borrow errors on services, CLIs, or libs who want design questions instead of copy-paste mut hacks.
Skip if: Beginners who have not read basic ownership yet, or pure syntax tutorials with no compiler errors to interpret.
When should I use this skill?
CRITICAL: Use for mutability issues; triggers include E0596, E0499, E0502, cannot borrow as mutable, interior mutability, Cell, RefCell, Mutex, RwLock.
What do I get? / Deliverables
You choose an ownership pattern—immutable transform, &mut, or appropriate interior/sync mutability—that compiles and matches who may change the data.
- Documented mutability strategy per type
- Refactor plan separating &mut vs interior vs synchronized mutation
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Most mutability design happens while implementing Rust modules, but the same skill applies when fixing compile failures before ship. Backend and systems Rust code is where ownership, &mut, and interior mutability choices affect every API surface.
Where it fits
Model a cache with shared mutation without handing every caller &mut across your HTTP handler types.
CI fails on E0502 in a unit test helper that holds an immutable borrow while calling a &mut method.
Production hot path needs atomics or RwLock instead of RefCell after moving code to a worker pool.
How it compares
Design-oriented Rust mutability playbook—not a blanket ‘add mut everywhere’ snippet list.
Common Questions / FAQ
Who is m03-mutability for?
Solo builders writing Rust backends or CLIs who encounter borrow checker errors and need structured guidance on mutability and interior mutability.
When should I use m03-mutability?
During Build backend implementation when modeling shared state, and during Ship when E0596/E0499/E0502 block tests or release builds; also when RefCell panics appear in single-threaded code.
Is m03-mutability safe to install?
It is advisory Rust guidance with no runtime side effects; review the Security Audits panel on this Prism page for the skill package integrity.
SKILL.md
READMESKILL.md - M03 Mutability
# 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 | Error | Don't Just Say | Ask 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 Error | Trace To | Question | |-----------------|----------|----------| | Repeated borrow conflicts | m09-domain | Should data be restructured? | | RefCell in async | m07-concurrency | Is Send/Sync needed? | | Mutex deadlocks | m07-concurrency | Is 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 | Pattern | Thread-Safe | Runtime Cost | Use When | |---------|-------------|--------------|----------| | `&mut T` | N/A | Zero | Exclusive mutable access | | `Cell<T>` | No | Zero | Copy types, no refs needed | | `RefCell<T>` | No | Runtime check | Non-Copy, need runtime borrow | | `Mutex<T>` | Yes | Lock contention | Thread-safe mutation | | `RwLock<T>` | Yes | Lock contention | Many readers, few writers | | `Atomic*` | Yes | Minimal | Simple types (bool, usize) | ## Error Code Reference | Error | Cause | Quick Fix | |-------|-------|-----------| | E0596 | Borrowing immutable as mutable | Add `mut` or redesign | | E0499 | Multiple mutable borrows | Restructure code flow | | E0502 | &mut while & exists | Separate borrow scopes | --- ## Interior Mutability Decision | Scenario | Choose | |----------|--------| | T: Copy, single-thread | `Cell<T>` | | T: !Copy, single-thread | `RefCell<T>` | | T: Copy, multi-thread | `AtomicXxx` | | T: !Copy, multi-thread | `Mutex<T>` or `RwLock<T>` | | Read-heavy, multi-thread | `RwLock<T>` | | Simple flags/counters | `AtomicBool`, `AtomicUsize` | --- ## Anti-Patterns | Anti-Pattern | Why Bad | Better | |--------------|---------|--------| | RefCell everywhere | Runtime panics | Clear ownership design | | Mutex for single-thread | Unnecessary overhead | RefCell | | Ignore RefCell panic | Hard to debug | Handle or restructure | | Lock inside hot loop | Performance killer | Batch operations | --- ## Related Skills | When | See | |------|-----| | Smart pointer choice | m02-resource | | Thread safety | m07-concurrency