Rust 的借用检查器在这里真正抱怨的是什么?

What is Rust's borrow checker really complaining about here?

考虑对 &mut Vec<&mut String> 进行简单的选择排序:

fn selection_sort(collection: &mut Vec<&mut String>) {
    for i in 0..collection.len() {
        let mut least_element = i;
        for j in (i + 1)..collection.len() {
            if collection[j] < collection[least_element] {
                least_element = j;
            }
        }

        collection.swap(least_element, i);
    }
}

这个循环应该工作,基于 this and that – 但借用抛出这个错误:

error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/main.rs:58:28
   |
58 |             if chunks[j] < chunks[least_element] {
   |                            ^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
   |
   = help: trait `IndexMut` is required to modify indexed content

或者在较新版本的 Rust 中:

error[E0596]: cannot borrow data in an index of `std::vec::Vec<&mut std::string::String>` as mutable
 --> src/lib.rs:5:32
  |
5 |             if collection[j] < collection[least_element] {
  |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
  |
  = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::vec::Vec<&mut std::string::String>`

让一个 & 引用可变不是更有意义吗?

IndexMut documentation 没有使用我理解的示例,并且有一个相当大的示例似乎没有清楚地演示如何使用 IndexMut,尤其是在选择的上下文中排序或交换元素。

Error 0596 解释当试图从不可变值借用时会发生这种情况,但 least_element 是可变的。如果 i 更改为 mut i 这也会编译(编译器建议从 i 中删除 mut)。

有没有大虾可以阐明这个?

当您尝试访问 collection[j] 时,编译器 returns 一个 &mut String 因为这是向量元素的类型。当您尝试访问 collection[least_element] 时,借用检查器不知道是否 least_element != j,并且对同一元素有两个可变引用将是未定义的行为。您可以使用 std::ops::Index which returns a &&mut String (并且对同一个可变引用有两个不可变引用是安全的),直接借用元素 (&collection[j] < &collection[least_element]) 或者,如果可能,将集合类型更改为 Vec<&String>Vec<String>.