其他
Rust 出现可变性/借用冲突(E0596、E0499…
在 Rust 中遇到 cannot borrow as mutable、借用冲突或需要内部可变性/线程安全可变性时,用于判断该不该可变、谁控制可变以及选哪种可变性原语。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 57/100 ×0.15
适用场景
Rust 出现可变性/借用冲突(E059特定
解决思路
- 在添加内部可变性前,先问:为什么这份数据需要改变,谁可以改变它;确认 mutation 是必要的还是偶然复杂度、谁应控制 mutation、mutation 模式是否安全。
- 遇到 E0596 时,不要只说“加 mut”,先问:这个数据真的需要可变吗?
- 遇到 E0499 时,不要只说“拆分借用”,先问:数据结构设计是否正确?
- 遇到 E0502 时,不要只说“分开作用域”,先问:为什么需要同时保留两个借用?
- 遇到 RefCell panic 时,不要只说“用 try_borrow”,先问:运行时检查是否合适?
- 添加可变性前判断 mutation 是否必要;若不必要,考虑 transform → 返回新值。
- 添加可变性前判断 mutation 是否必要;若在构造对象,考虑 builder → 不可变构造。
- 添加可变性前判断谁控制 mutation:外部调用方控制 → 用 `&mut T`。
- 添加可变性前判断谁控制 mutation:内部逻辑控制 → 用 interior mutability。
- 添加可变性前判断谁控制 mutation:并发访问控制 → 用 synchronized mutability。
- 添加可变性前判断线程上下文:单线程 → 选 `Cell`/`RefCell`。
- 添加可变性前判断线程上下文:多线程 → 选 `Mutex`/`RwLock`/`Atomic`。
- 当可变性冲突持续存在(E0499/E0502 借用冲突)时,向上追溯:问数据结构设计是否正确,检查 m09-domain(数据是否该拆分),检查 m07-concurrency(是否涉及 async)。
- 反复出现借用冲突 → 追溯到 m09-domain,问是否应重构数据结构。
- 在 async 中使用 RefCell → 追溯到 m07-concurrency,问是否需要 `Send`/`Sync`。
- Mutex 死锁 → 追溯到 m07-concurrency,问锁的设计是否正确。
- 从设计到实现:需要从 `&self` 获得可变访问时,若 `T: Copy` → 用 `Cell<T>`。
- 从设计到实现:需要从 `&self` 获得可变访问时,若 `T: !Copy` → 用 `RefCell<T>`。
- 从设计到实现:需要线程安全 mutation 时,简单计数器 → 用 `AtomicXxx`。
- 从设计到实现:需要线程安全 mutation 时,复杂数据 → 用 `Mutex<T>` 或 `RwLock<T>`。
- 从设计到实现:需要共享可变状态时,单线程 → 用 `Rc<RefCell<T>>`。
- 从设计到实现:需要共享可变状态时,多线程 → 用 `Arc<Mutex<T>>`。
- 遵守借用规则:任一时刻只能有多个 `&T`(不可变借用)或一个 `&mut T`(可变借用),绝不能同时存在两者。
- 需要独占可变访问 → 用 `&mut T`(线程安全不适用,运行时开销为零)。
- Copy 类型且不需要引用 → 用 `Cell<T>`(非线程安全,运行时开销为零)。
- 非 Copy 类型且需要运行时借用检查 → 用 `RefCell<T>`(非线程安全,有运行时检查开销)。
- 需要线程安全 mutation → 用 `Mutex<T>`(线程安全,有锁竞争开销)。
- 读多写少的多线程场景 → 用 `RwLock<T>`(线程安全,有锁竞争开销)。
- 简单类型(bool、usize 等)的线程安全 mutation → 用 `Atomic*`(线程安全,开销最小)。
- 错误 E0596:把不可变借用当作可变借用;快速修复是加 `mut` 或重新设计。
- 错误 E0499:多个可变借用;快速修复是重构代码流程。
- 错误 E0502:存在 `&` 时使用 `&mut`;快速修复是分离借用作用域。
- 内部可变性决策:`T: Copy` 且单线程 → `Cell<T>`。
- 内部可变性决策:`T: !Copy` 且单线程 → `RefCell<T>`。
- 内部可变性决策:`T: Copy` 且多线程 → `AtomicXxx`。
- 内部可变性决策:`T: !Copy` 且多线程 → `Mutex<T>` 或 `RwLock<T>`。
- 内部可变性决策:多线程读密集 → `RwLock<T>`。
- 内部可变性决策:简单标志/计数器 → `AtomicBool`、`AtomicUsize`。
- 避免反模式:不要到处用 RefCell;会导致运行时 panic,应设计清晰的所有权。
- 避免反模式:不要为单线程用 Mutex;会有不必要开销,应改用 RefCell。
- 避免反模式:不要忽略 RefCell panic;难以调试,应处理或重构。
- 避免反模式:不要在热循环内加锁;会成为性能杀手,应批量操作。
- 相关技能:智能指针选择参考 m02-resource;线程安全参考 m07-concurrency;数据结构设计参考 m09-domain;反模式参考 m15-anti-pattern。
适用边界 · 注意事项
- 不适用于非 Rust 项目,或没有所有权/借用检查器、E0596/E0499/E0502 这类错误的语言。
- 没有可变性或借用冲突问题时,不需要套用内部可变性/锁的选择规则。
- 不要用本技能替代具体业务/并发架构设计;它只处理 Rust 可变性机制。