Versi yang diinginkan sedikit berbeda dari yang Anda miliki. Garis
v[v[1]] = 999;
sebenarnya keinginan untuk
*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
Ini menghasilkan pesan kesalahan yang sama, tetapi anotasi memberikan petunjuk tentang apa yang terjadi:
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
Perbedaan penting dengan versi yang Anda inginkan adalah urutan evaluasi. Argumen panggilan fungsi dievaluasi dari kiri ke kanan dalam urutan yang tercantum, sebelum benar-benar membuat panggilan fungsi. Dalam hal ini ini berarti bahwa pertama &mut v
dievaluasi, saling meminjam v
. Selanjutnya, Index::index(&v, 1)
harus dievaluasi, tetapi ini tidak mungkin - v
sudah dipinjam secara gonta-ganti. Akhirnya, kompiler menunjukkan bahwa referensi yang dapat diubah masih diperlukan untuk pemanggilan fungsi index_mut()
, sehingga referensi yang dapat diubah masih hidup ketika referensi bersama dicoba.
Versi yang sebenarnya mengkompilasi memiliki urutan evaluasi yang sedikit berbeda.
*v.index_mut(*v.index(1)) = 999;
Pertama, argumen fungsi untuk panggilan metode dievaluasi dari kiri ke kanan, yaitu *v.index(1)
dievaluasi terlebih dahulu. Ini menghasilkan usize
, dan pinjaman sementara sementara v
dapat dirilis kembali. Kemudian, penerima index_mut()
dievaluasi, yaitu v
dipinjam bersama. Ini berfungsi dengan baik, karena pinjaman bersama telah diselesaikan, dan seluruh ekspresi melewati pemeriksa pinjaman.
Perhatikan bahwa versi yang mengkompilasi hanya melakukannya sejak diperkenalkannya "masa hidup non-leksikal". Dalam versi Rust yang lebih lama, pinjaman bersama akan hidup sampai akhir ekspresi dan menghasilkan kesalahan yang sama.
Solusi terbersih menurut saya adalah menggunakan variabel sementara:
let i = v[1];
v[i] = 999;