为什么编译器错误抱怨多个可变引用而不是悬挂引用?

Why does the compiler error complain about multiple mutable references not dangling reference?

我想了解当函数重新借用可变引用时到底发生了什么。

fn main() {
    let mut a = String::new();
    let mut b = String::new();
    let aa = &mut a;
    let c = my_fun(aa, &mut b);
    let d = &mut a;
    println!("{}", c);
}
                
fn my_fun<'b>(x: &'b mut String, y: &'b mut String) -> &'b mut String { y }

根据我的理解,my_funaa 重新借用为 &*aa,其范围将是 my_fun。但是由于我在函数签名中创建的生命周期限制,重新借用应该至少在 &mut b 存在时存在。所以 println 强制重新借用直到它。

这不应该在 free 之后抛出一个使用错误,因为匿名重借的范围只在 my_fun 内吗?在这个函数之外,这个引用应该是无效的。

但我得到的错误是:

error[E0499]: cannot borrow `a` as mutable more than once at a time
 --> src/main.rs:7:13
  |
5 |     let aa= &mut a;
  |             ------ first mutable borrow occurs here
6 |     let c = my_fun(aa, &mut b);
7 |     let d = &mut a;
  |             ^^^^^^ second mutable borrow occurs here
8 |     println!("{}", c);
  |                    - first borrow later used 

如果可变引用只是被复制而不是在函数内部重新借用,这将是有意义的。

我相信你在这里“重新借用”想得太多了。

您应用的生命周期要求表明,return 值引用的事物至少具有参数引用事物的生命周期。这是真的(如果不能证明是真的,这将无法编译)。所以不可能有悬空引用。

没有单独的“重借”引用。借用是编译器内部的簿记,以跟踪生命周期。没有 let x = &*aa 实际发生或什至特别暗示的步骤。这不像引用计数,内存在运行时实际发生变化。

my_fun 内部,y 是作用域为函数的引用。但是 return 值 仅限于调用者。 (如果不是这样,函数将无法使用,与 &mut 无关。)

From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun.

不完全是这样。

让我们回顾一下:为什么要重新借用?

&T&mut T有一个根本的区别:&TCopy,而&mut T甚至不是Clone。结果是 &mut T 只能被 移动 因此调用如:

let x: &mut T = /*...*/;
func(x);

会导致 x 在调用后无法使用。解决方法是引入一个临时的:

let x: &mut T = /*...*/;
let tmp = &mut *x;
func(tmp);

这个临时对象会重新借用 x 的指针,并被 func 使用。

还有...那是再借!编译器内置了这个纯粹为了人体工程学的“临时”创建!

考虑到这一点,让我们回到:

From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun.

寿命通常是 范围 而不是 ,这里也是如此。

上面示例中 tmp 的生命周期受到两种方式的限制:

  • 不能大于x
  • 不能小于func

这是另一种说法,它可以是这些界限之间的 任何东西