m03-mutability
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMutability
可变性
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? |
| 错误 | 不要只说 | 而应询问 |
|---|---|---|
| E0596 | "添加mut" | 这个变量真的需要是可变的吗? |
| E0499 | "拆分借用" | 数据结构的设计是否合理? |
| E0502 | "分离作用域" | 我们为什么同时需要两种借用? |
| RefCell 恐慌 | "使用try_borrow" | 运行时检查是否合适? |
Thinking Prompt
思考提示
Before adding mutability:
-
Is mutation necessary?
- Maybe transform → return new value
- Maybe builder → construct immutably
-
Who controls mutation?
- External caller →
&mut T - Internal logic → interior mutability
- Concurrent access → synchronized mutability
- External caller →
-
What's the thread context?
- Single-thread → Cell/RefCell
- Multi-thread → Mutex/RwLock/Atomic
在添加可变性之前:
-
变更是必需的吗?
- 或许可以通过转换→返回新值的方式实现
- 或许可以使用构建器模式→以不可变方式构造对象
-
谁控制变更?
- 外部调用者 →
&mut T - 内部逻辑 → 内部可变性
- 并发访问 → 同步化可变性
- 外部调用者 →
-
线程上下文是什么?
- 单线程 → Cell/RefCell
- 多线程 → 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? |
当可发性冲突持续存在时:
E0499/E0502 (借用冲突)
↑ 询问:数据结构的设计是否正确?
↑ 检查:m09-domain(是否需要拆分数据?)
↑ 检查:m07-concurrency(是否涉及异步?)| 持续出现的错误 | 追溯至 | 问题 |
|---|---|---|
| 反复出现借用冲突 | m09-domain | 是否需要重构数据结构? |
| 异步场景中使用RefCell | m07-concurrency | 是否需要Send/Sync特性? |
| Mutex死锁 | m07-concurrency | 锁的设计是否合理? |
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>>从设计到实现:
"需要从&self中进行可变访问"
↓ T: Copy → Cell<T>
↓ T: !Copy → RefCell<T>
"需要线程安全的变更"
↓ 简单计数器 → AtomicXxx
↓ 复杂数据 → Mutex<T> 或 RwLock<T>
"需要共享可变状态"
↓ 单线程: Rc<RefCell<T>>
↓ 多线程: 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.在任何时刻,你只能拥有以下其中一种情况:
├─ 多个&T(不可变借用)
└─ 或者一个&mut T(可变借用)
绝不能同时拥有两者。Quick Reference
速查参考
| Pattern | Thread-Safe | Runtime Cost | Use When |
|---|---|---|---|
| N/A | Zero | Exclusive mutable access |
| No | Zero | Copy types, no refs needed |
| No | Runtime check | Non-Copy, need runtime borrow |
| Yes | Lock contention | Thread-safe mutation |
| Yes | Lock contention | Many readers, few writers |
| Yes | Minimal | Simple types (bool, usize) |
| 模式 | 线程安全 | 运行时开销 | 使用场景 |
|---|---|---|---|
| 不适用 | 零 | 独占式可变访问 |
| 否 | 零 | 可Copy类型,无需引用 |
| 否 | 运行时检查 | 不可Copy类型,需要运行时借用 |
| 是 | 锁竞争开销 | 线程安全的变更 |
| 是 | 锁竞争开销 | 读多写少场景 |
| 是 | 极小 | 简单类型(bool、usize) |
Error Code Reference
错误码参考
| Error | Cause | Quick Fix |
|---|---|---|
| E0596 | Borrowing immutable as mutable | Add |
| E0499 | Multiple mutable borrows | Restructure code flow |
| E0502 | &mut while & exists | Separate borrow scopes |
| 错误 | 原因 | 快速修复方案 |
|---|---|---|
| E0596 | 以可变方式借用不可变变量 | 添加 |
| E0499 | 多次可变借用 | 重构代码流程 |
| E0502 | 存在&借用时同时使用&mut | 分离借用作用域 |
Interior Mutability Decision
内部可变性决策指南
| Scenario | Choose |
|---|---|
| T: Copy, single-thread | |
| T: !Copy, single-thread | |
| T: Copy, multi-thread | |
| T: !Copy, multi-thread | |
| Read-heavy, multi-thread | |
| Simple flags/counters | |
| 场景 | 选择 |
|---|---|
| T: Copy,单线程 | |
| T: !Copy,单线程 | |
| T: Copy,多线程 | |
| T: !Copy,多线程 | |
| 读多写少,多线程 | |
| 简单标志/计数器 | |
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 |
| 反模式 | 危害 | 更佳方案 |
|---|---|---|
| 到处使用RefCell | 可能导致运行时恐慌 | 清晰的所有权设计 |
| 单线程场景使用Mutex | 不必要的开销 | 使用RefCell |
| 忽略RefCell恐慌 | 难以调试 | 处理错误或重构代码 |
| 热循环内加锁 | 严重影响性能 | 批量操作 |
Related Skills
相关技能
| When | See |
|---|---|
| Smart pointer choice | m02-resource |
| Thread safety | m07-concurrency |
| Data structure design | m09-domain |
| Anti-patterns | m15-anti-pattern |
| 场景 | 参考 |
|---|---|
| 智能指针选择 | m02-resource |
| 线程安全 | m07-concurrency |
| 数据结构设计 | m09-domain |
| 反模式 | m15-anti-pattern |