รุ่นที่ได้รับการออกแบบแตกต่างจากที่คุณมีเล็กน้อย เส้น
v[v[1]] = 999;
อันที่จริงควรทำ
*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)
ถูกประเมินก่อน สิ่งนี้ส่งผลให้ a usize
และเงินกู้ชั่วคราวที่ใช้ร่วมกันของv
สามารถออกใหม่ได้อีกครั้ง จากนั้นindex_mut()
จะทำการประเมินผู้รับซึ่งv
ก็คือการยืมอย่างไม่แน่นอน วิธีนี้ใช้งานได้ดีเนื่องจากการกู้ที่ใช้ร่วมกันได้รับการสรุปแล้วและการแสดงออกทั้งหมดผ่านการตรวจสอบการยืม
โปรดทราบว่ารุ่นที่คอมไพล์ทำได้ตั้งแต่เปิดตัว "อายุคำศัพท์ที่ไม่ใช่คำศัพท์" ในรุ่นก่อนหน้าของ Rust การยืมที่ใช้ร่วมกันจะมีชีวิตอยู่จนถึงจุดสิ้นสุดของนิพจน์และทำให้เกิดข้อผิดพลาดที่คล้ายกัน
ทางออกที่สะอาดที่สุดในความคิดของฉันคือการใช้ตัวแปรชั่วคราว:
let i = v[1];
v[i] = 999;