A versão sugerida é um pouco diferente do que você tem. A linha
v[v[1]] = 999;
realmente desugars para
*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
Isso resulta na mesma mensagem de erro, mas as anotações dão uma dica do que está acontecendo:
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
A diferença importante para sua versão desejada é a ordem de avaliação. Os argumentos de uma chamada de função são avaliados da esquerda para a direita na ordem listada, antes de realmente fazer a chamada de função. Nesse caso, isso significa que primeiro &mut v
é avaliado, mutuamente emprestado v
. Em seguida, Index::index(&v, 1)
deve ser avaliado, mas isso não é possível -v
já é mutuamente emprestado. Finalmente, o compilador mostra que a referência mutável ainda é necessária para a chamada de função index_mut()
, portanto, a referência mutável ainda está ativa quando a referência compartilhada é tentada.
A versão que realmente compila tem uma ordem de avaliação ligeiramente diferente.
*v.index_mut(*v.index(1)) = 999;
Primeiro, os argumentos da função para as chamadas do método são avaliados da esquerda para a direita, ou seja, *v.index(1)
são avaliados primeiro. Isso resulta em usize
ae o empréstimo compartilhado temporário de v
pode ser liberado novamente. Então, o receptor de index_mut()
é avaliado, ou seja,v
é mutuamente emprestado. Isso funciona bem, pois o empréstimo compartilhado já foi finalizado e toda a expressão passa no verificador de empréstimo.
Observe que a versão que compila apenas o faz desde a introdução de "vidas úteis não-lexicais". Nas versões anteriores do Rust, o empréstimo compartilhado permaneceria até o final da expressão e resultaria em um erro semelhante.
A solução mais limpa na minha opinião é usar uma variável temporária:
let i = v[1];
v[i] = 999;