“由二者归纳可得:良类型闭项的任意有限求值前缀都不会到达一个既非值又无后继的卡住项。有存储、异常或并发时,需要把判断扩展到配置,并加入存储良类型、允许的最终结果等不变量。效应系统还要让运行时实…”
形式陈述 ​
本页先固定一个 Rust-like core calculus,只含 owner、move、共享借用、独占借用和区域生命周期;它用来说明共同静态不变量,不等同于某个 Rust 编译器版本的完整 borrow checker。Rust 的 non-lexical lifetimes、variance、interior mutability 与 two-phase borrows 会在边界处单独说明,不能反向当作所有权系统的一般定理。
在核心演算中,每项资源有一个负责其有效性和最终释放的 owner。移动(move)把这项责任从源绑定转给目标绑定;移动完成后,源绑定处于不可读状态,直到它被重新赋值。这个规则约束的是被移动值的责任,不是说源变量在整段程序里只能出现一次,也不妨碍显式标记为可复制的值按语言规则复制。
借用在不转移所有权的情况下临时授予访问能力。用
- 可以同时存在多个有效共享借用,但它们只提供读访问;
- 或者存在一个有效独占借用,它可读写该位置;
- 两种状态不能重叠,独占借用之间也不能重叠;
- 每个借用的生命周期都包含在所有者和被借对象仍有效的区间内。
若
在共享借用有效期间,不能移动或可变访问
在这个核心模型中,生命周期可形成子类型或区域包含关系。若
独占引用通常通过 reborrowing 获得较短的
这些约束属于静态语义。借用检查算法可以用词法作用域、数据流或非词法生命周期推断
直觉 ​
所有权回答“谁负责让这项资源继续有效并最终收尾”,借用回答“在责任不转手时,谁能暂时看或改它”。move 像交接钥匙和保管责任,旧持有人不能继续开门;shared borrow 像发出若干只读访客证,exclusive borrow 则像暂时把唯一工作证交给维护者。
生命周期不是对象实际存活秒数,而是静态证明中一次引用可能被使用的程序区域。只要编译器能证明借用在最后一次使用后结束,就可以恢复所有者访问;非词法生命周期因此比“必须等到花括号结束”更精确,却不改变核心排他不变量。
例子与边界 ​
设向量 v 拥有一段可能在扩容时迁移的缓冲区,p = &v[0] 创建指向元素的共享借用。只要 p 后续仍会使用,执行 v.push(x) 就需要可变借用整个向量,并可能让缓冲区换址;它既与现有共享借用冲突,也可能使 p 悬空,所以静态规则拒绝这段重叠。p 最后一次使用后,短生命周期结束,push 才可获得独占访问。
对拥有堆字符串的值,let b = move a 把释放责任交给 b,随后读取 a 会被拒绝;若重新给 a 赋一个新字符串,它又成为新值的 owner。整数等 Copy 值可以显式复制而不使源失效,这说明所有权不等于“每个变量只能用一次”。
共享所有权和内部可变性是 Rust 层的重要边界。Rc/Arc 通过引用计数让多个 owner 共同保持分配存活;RefCell 把共享/独占检查推迟到运行时,违规时失败;Mutex 通过加锁在并发访问中动态取得独占权限。这些库类型改变检查发生的位置,却不是核心演算里“共享借用只读”的反例:可变操作必须经过额外的动态协议。unsafe 代码还可绕过静态限制,但必须由程序员或库证明恢复调用方看到的安全不变量。
Two-phase borrow 是另一项 Rust 特定规则。某些方法接收者的可变借用先处于 reservation 阶段,允许在真正调用前完成受限的共享求值,例如计算 v.push(v.len()) 的参数;到 activation 后才取得独占访问。它不允许两个任意写者重叠,也不是对所有 &mut 表达式开放的通则,所以核心模型仍用单阶段独占借用陈述不变量。
线程间可否移动或共享值还需要类似 Send/Sync 的能力约束。所有权与借用能排除一类悬空引用和冲突别名,却不自动证明锁顺序正确、程序无死锁或所有数据访问都无竞争。
推论与应用 ​
所有权系统常借鉴线性与仿射类型的不可复制资源观念:move 类似消费旧能力并产生新能力。但所有权还要描述堆位置、共享只读别名、临时独占、生命周期包含与 reborrow;普通线性演算并不自动给出这些规则。因此所有权不是线性类型的语法糖,Rust 变量也不是普遍线性值。
编译器可利用独占借用推断某段时间没有竞争别名,从而安全地原地更新或优化访问。验证这类优化仍需连接静态 loan 事实与运行存储:若 interior mutability、外部函数或 unsafe 边界能绕过别名承诺,优化器必须依赖更精确的语言内存模型和库契约。
参考资料
- The Rust Reference,ownership, references, subtyping, and variance;The Rustonomicon,unsafe abstractions and aliasing。
- Ralf Jung et al., “RustBelt: Securing the Foundations of the Rust Programming Language,” POPL, 2018。
- Nicholas D. Matsakis and Felix S. Klock II, “The Rust Language,” ACM SIGAda Ada Letters 34(3), 2014,ownership and borrowing model。