2.5.6 嵌套借用与不变性

译文 · 基于 Learning Rust

嵌套借用与不变性

原文链接: https://quinedot.github.io/rust-learning/st-invariance.html

现在让我们考虑嵌套引用:

  • &'medium &'long U 可以强制转换为 &'short &'short U
  • &'medium mut &'long mut U 可以强制转换为 &'short mut &'long mut U……
    • ……但不能转换为 &'short mut &'short mut U

我们说 &mut T 在 T 上是不变的(invariant),这意味着 T 中的任何生命周期都完全不能改变(变长或变短)。在上面的例子中,T 是 &'long mut U,而 'long 不能被改变。

为什么不行?考虑这个例子:

1
2
3
4
5
fn bar(v: &mut Vec<&'static str>) {
    let w: &mut Vec<&'_ str> = v; // 将此生命周期称为 'w
    let local = "Gottem".to_string();
    w.push(&*local);
} // `local` 在此处被销毁

如果允许 'w 比 'static 更短,那么在 bar 返回后,*v 中就会出现悬垂引用。

在使用引用时,你不可避免地会对协变性(covariance)产生直觉——因为外层生命周期很灵活——但最终会遇到不变性(invariance)很重要并导致借用检查错误的情况,因为它(必然地)灵活得多。这只是 Rust 学习经历的一部分。


再来看一个你可能遇到的嵌套引用的性质:

  • 你可以从 &'short &'long U 得到 &'long U:
    • 直接把它复制出来就行!
  • 但你不能通过对 &'short mut &'long mut U 解引用来得到 &'long mut U。

原因同样是为了防止内存不安全。

此外,

  • 你不能从 &'short &'long mut U 得到 &'long U 或任何 &mut U
    • 你只能重借用一个 &'short U

回想一下,一旦存在共享引用,就可能同时存在任意数量的副本。因此,只要外层共享引用存在(并可能被用来观察 U),内部的 &mut 就不能以可变或其他独占方式使用。

而一旦外层引用失效,内部的 &mut 就重新生效,必须再次独占,因此也不可能获得 &'long U。

最后修改 August 23, 2026: 更新 (499855b16)