अवरोही संस्करण आपके पास की तुलना में थोड़ा अलग है। रेखा
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
पारस्परिक रूप से उधार लिया जाता है। यह ठीक काम करता है, क्योंकि साझा उधार को पहले ही अंतिम रूप दिया जा चुका है, और पूरी अभिव्यक्ति उधारकर्ता को पास करती है।
ध्यान दें कि जो संस्करण केवल संकलित करता है वह "गैर-शाब्दिक जीवनकाल" की शुरुआत के बाद से करता है। रस्ट के पुराने संस्करणों में, साझा उधार अभिव्यक्ति के अंत तक जीवित रहेगा और एक समान त्रुटि के परिणामस्वरूप होगा।
मेरी राय में सबसे साफ समाधान एक अस्थायी चर का उपयोग करना है:
let i = v[1];
v[i] = 999;