Phiên bản desugared hơi khác so với những gì bạn có. Dòng
v[v[1]] = 999;
thực sự desugars để
*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
Điều này dẫn đến cùng một thông báo lỗi, nhưng các chú thích đưa ra gợi ý về những gì đang xảy ra:
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
Sự khác biệt quan trọng đối với phiên bản bỏ hoang của bạn là thứ tự đánh giá. Các đối số của một lệnh gọi hàm được đánh giá từ trái sang phải theo thứ tự được liệt kê, trước khi thực sự thực hiện cuộc gọi hàm. Trong trường hợp này, điều này có nghĩa là đầu tiên &mut v
được đánh giá, vay tương đối v
. Tiếp theo, Index::index(&v, 1)
nên được đánh giá, nhưng điều này là không thể -v
đã được vay mượn lẫn nhau. Cuối cùng, trình biên dịch cho thấy rằng tham chiếu có thể thay đổi vẫn cần thiết cho lệnh gọi hàm index_mut()
, vì vậy tham chiếu có thể thay đổi vẫn còn tồn tại khi tham chiếu chia sẻ được thử.
Phiên bản thực sự biên dịch có thứ tự đánh giá hơi khác nhau.
*v.index_mut(*v.index(1)) = 999;
Đầu tiên, các đối số hàm cho các lệnh gọi phương thức được ước tính từ trái sang phải, tức *v.index(1)
là được ước tính trước. Điều này dẫn đến một usize
, và khoản vay chia sẻ tạm thời v
có thể được phát hành lại. Sau đó, người nhậnindex_mut()
được đánh giá, tức v
là được vay mượn. Điều này hoạt động tốt, vì khoản vay được chia sẻ đã được hoàn thành và toàn bộ biểu thức vượt qua trình kiểm tra khoản vay.
Lưu ý rằng phiên bản biên dịch chỉ làm như vậy kể từ khi giới thiệu "vòng đời phi từ vựng". Trong các phiên bản trước của Rust, khoản vay được chia sẻ sẽ tồn tại cho đến khi kết thúc biểu thức và dẫn đến một lỗi tương tự.
Theo tôi, giải pháp sạch nhất là sử dụng một biến tạm thời:
let i = v[1];
v[i] = 999;