Rust `Vec` - 不能在 `impl` 方法中借用 `Vec` 作为不可变的(错误 [E0502])

Rust `Vec` - cannot borrow `Vec` as immutable inside `impl` method (error[E0502])

关于 Rust 的 error[E0502] 的问题有很多答案,但我无法真正理解一个特定的案例。我有一个 struct,它的 impl 方法是这样的:

struct Test {
  test_vec: Vec<i32>,
}

impl Test {
  // other methods...

  fn test(&mut self) -> i32 {
    self.test_vec.swap(0, self.test_vec.len() - 1);

    // other operations...
  }
}

尝试立即编译会导致错误:

error[E0502]: cannot borrow self.test_vec as immutable because it is also borrowed as mutable

self.test_vec.swap(0, self.test_vec.len() - 1);
------------- ----    ^^^^^^^^^^^^^ immutable borrow occurs here
|             |
|             mutable borrow later used by call
mutable borrow occurs here

谁能解释一下为什么?看起来我并不是想在那里借用 self.test_vec,我正在传递 len() 调用的 usize 类型结果。另一方面:

fn test(&mut self) -> i32 {
  let last_index = self.test_vec.len() - 1;

  self.test_vec.swap(0, last_index);

  // other operations...
}

使用临时变量,它按预期工作,让我认为 len() 调用以某种方式被评估 它到达 swap 之后,并且从而被借用?我是不是因为语法糖而看不到东西?

您必须以编译器的方式来考虑这一点。当你写:

self.test_vec.swap(0, self.test_vec.len() - 1);

编译器看到的内容:

let temp1 = &mut self.test_vec;      // Mutable borrow of self.test_vec
let temp2 = &self.test_vec;          // (ERROR!) Shared borrow of self.test_vec for use on getting the length
let temp3 = Vec::len(temp2) - 1; 
Vec::swap(temp1, 0, temp3);

如你所见,你是先可变地借用self.test_vec,然后再尝试获取长度,这又是一次借用。由于第一次借用是可变的并且仍然有效,第二次借用是非法的。

当您使用临时变量时,您实际上是在重新排序借用,并且由于 self.test_vec.len() 在下一个可变借用之前终止借用,因此没有冲突。

您可以争辩说编译器应该能够看到您的代码是正确的(如果以正确的方式解释),但编译器显然还不够聪明,无法做到这一点。