Версия desugared немного отличается от того, что у вас есть. Линия
v[v[1]] = 999;
на самом деле desugars к
*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
Это приводит к тому же сообщению об ошибке, но аннотации дают подсказку о том, что происходит:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:7:48
|
7 | *IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
| ------------------- ------ ^^ immutable borrow occurs here
| | |
| | mutable borrow occurs here
| mutable borrow later used by call
Важным отличием вашей исходной версии является порядок оценки. Аргументы вызова функции оцениваются слева направо в указанном порядке до фактического вызова функции. В этом случае это означает, что сначала&mut v оценивается, заимствуя заимствования v. Далее Index::index(&v, 1)следует оценить, но это невозможно - vуже заимствовано. Наконец, компилятор показывает, что изменяемая ссылка все еще необходима для вызова функции index_mut(), поэтому изменяемая ссылка все еще жива, когда делается попытка использования общей ссылки.
Версия, которая на самом деле компилируется, имеет немного другой порядок оценки.
*v.index_mut(*v.index(1)) = 999;
Во-первых, аргументы функции для вызовов метода оцениваются слева направо, т.е. *v.index(1)оцениваются первыми. Это приводит кusize , что временный общий заем vможет быть освобожден снова. Затем получатель index_mut()оценивается, то vесть заимствован. Это работает нормально, поскольку общий заем уже завершен, и все выражение проходит проверку заимствования.
Обратите внимание, что версия, которая компилируется, делает это только после введения «нелексических времен жизни». В более ранних версиях Rust общее заимствование сохранялось до конца выражения и приводило к аналогичной ошибке.
На мой взгляд, самое чистое решение - использовать временную переменную:
let i = v[1];
v[i] = 999;