m03-mutability

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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?

错误不要只说而应询问
E0596"添加mut"这个变量真的需要是可变的吗?
E0499"拆分借用"数据结构的设计是否合理?
E0502"分离作用域"我们为什么同时需要两种借用?
RefCell 恐慌"使用try_borrow"运行时检查是否合适?

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

在添加可变性之前:
  1. 变更是必需的吗?
    • 或许可以通过转换→返回新值的方式实现
    • 或许可以使用构建器模式→以不可变方式构造对象
  2. 谁控制变更?
    • 外部调用者 →
      &mut T
    • 内部逻辑 → 内部可变性
    • 并发访问 → 同步化可变性
  3. 线程上下文是什么?
    • 单线程 → 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 ErrorTrace ToQuestion
Repeated borrow conflictsm09-domainShould data be restructured?
RefCell in asyncm07-concurrencyIs Send/Sync needed?
Mutex deadlocksm07-concurrencyIs the lock design right?

当可发性冲突持续存在时:
E0499/E0502 (借用冲突)
    ↑ 询问:数据结构的设计是否正确?
    ↑ 检查:m09-domain(是否需要拆分数据?)
    ↑ 检查:m07-concurrency(是否涉及异步?)
持续出现的错误追溯至问题
反复出现借用冲突m09-domain是否需要重构数据结构?
异步场景中使用RefCellm07-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

速查参考

PatternThread-SafeRuntime CostUse When
&mut T
N/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)
模式线程安全运行时开销使用场景
&mut T
不适用独占式可变访问
Cell<T>
可Copy类型,无需引用
RefCell<T>
运行时检查不可Copy类型,需要运行时借用
Mutex<T>
锁竞争开销线程安全的变更
RwLock<T>
锁竞争开销读多写少场景
Atomic*
极小简单类型(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

错误原因快速修复方案
E0596以可变方式借用不可变变量添加
mut
或重新设计
E0499多次可变借用重构代码流程
E0502存在&借用时同时使用&mut分离借用作用域

Interior Mutability Decision

内部可变性决策指南

ScenarioChoose
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

场景选择
T: Copy,单线程
Cell<T>
T: !Copy,单线程
RefCell<T>
T: Copy,多线程
AtomicXxx
T: !Copy,多线程
Mutex<T>
RwLock<T>
读多写少,多线程
RwLock<T>
简单标志/计数器
AtomicBool
,
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

反模式危害更佳方案
到处使用RefCell可能导致运行时恐慌清晰的所有权设计
单线程场景使用Mutex不必要的开销使用RefCell
忽略RefCell恐慌难以调试处理错误或重构代码
热循环内加锁严重影响性能批量操作

Related Skills

相关技能

WhenSee
Smart pointer choicem02-resource
Thread safetym07-concurrency
Data structure designm09-domain
Anti-patternsm15-anti-pattern
场景参考
智能指针选择m02-resource
线程安全m07-concurrency
数据结构设计m09-domain
反模式m15-anti-pattern