Consider a simple selection sort on a &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 loop should work, based on this and that – yet the borrow throws this error:
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
Or in newer versions of 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>`
Wouldn't it make more sense to have a &
reference be mutable?
The IndexMut
documentation doesn't use an example I understand well and has a pretty large example that doesn't seem to clearly demonstrate how to use IndexMut
, especially in the context of a selection sort, or swapping elements.
Error 0596 explains it occurs when trying to borrow from an immutable value, yet least_element
is mutable. If i
is changed to mut i
this also does compile (and the compiler recommends removing mut
from i
).
Is there a Rustacean who can illuminate this?
Index
orIndexMut
while deciding the override ofPartialEq::lt
to use. You can workaround with a couple of temporary variables such aslet a = &collection[j]; let b = &collection[least_element]; if a < b ...
- rodrigouse std::ops::Index;
and writeif collection.index(j) < collection.index[least_element] ...
- rodrigoif collection[j].lt(&collection[least_element]) ...
. I'm starting to think that you may have found a compiler bug... - rodrigo&collection[j] < &collection[least_element]
also works. Don't know why though. - mcarton*collection[j] < *collection[least_element]
- mcarton