直接回答:它们是 Rust 为 unsafe 代码定义“什么时候两个指针允许指向同一内存、允许谁读谁写”的操作语义模型。安全代码的借用规则由编译器检查,unsafe 里的裸指针编译器管不了,但优化器仍假设别名规则成立——违反就是 UB, Miri 用这套模型动态检测。核心思想:每个引用/指针的产生与再借用形成一棵栈或树,父指针的有效性依赖子指针链,越界访问(如用过期的父指针写子指针活跃期间的内存)即违规。
展开解析:为什么重要:LLVM 级别的优化(noalias 标注)基于这些假设做重排与缓存,UB 不保证“实际跑起来没事”,换个优化级别行为就可能变。实践含义:unsafe 代码里拿到裸指针后尽快缩小其作用范围,避免长寿命裸指针与活跃引用交叉使用;尽量用 &mut 而不是到处 *mut,让检查器能帮上忙;涉及 self-referential 结构、侵入式链表这类天然别名密集的场景,考虑用 Pin、arena 索引或 UnsafeCell 精确声明可变性边界。Tree Borrows 是 Stacked Borrows 的继任者,放宽了一些过严的限制(特别是对共享引用的读),细节仍在演进。工程建议:unsafe 模块配 Miri 跑测试(miri 能抓到未初始化读、越界、别名违规),这是 unsafe 代码的事实标准验证手段。
追问方向:UnsafeCell 在别名模型里扮演什么角色?为什么 transmute 生命周期是危险的?
(约 480 字)