एकाधिक उत्परिवर्तनीय संदर्भों के कारण किसी संरचना के सदस्य को खुद को सौंपना असंभव हो जाता है? [डुप्लिकेट]

Aug 17 2020

मैं उधार लेने में सक्षम नहीं हूं जहां मुझे लगा कि मैं कर सकता हूं। मैंने इस मामले में समस्या को कम किया:

struct A<'a> {
    borrow: &'a mut u8,
}

fn does_nothing<'b, 'c>(a: &'b mut A<'c>) {
    a.borrow = a.borrow;
}
error[E0623]: lifetime mismatch
 --> src/lib.rs:6:16
  |
5 | fn does_nothing<'b, 'c>(a: &'b mut A<'c>) {
  |                            -------------
  |                            |
  |                            these two types are declared with different lifetimes...
6 |     a.borrow = a.borrow;
  |                ^^^^^^^^ ...but data from `a` flows into `a` here

ऐसा लगता है कि a.borrowका चौराहा है 'bऔर 'cइसलिए अभी भी जीवन भर की गारंटी नहीं दी जा सकती है 'c

मुझे इससे कोई वास्तविक समस्या नहीं है और दोनों जीवन भर एक ही बनाकर इसके चारों ओर काम कर सकते हैं, लेकिन यह चेक उधार क्यों नहीं लेता है?


ऐसा लगता है कि इस मुद्दे को दिखाने के लिए संरचनाएं महत्वहीन हैं और दोहरे उधार इसे आसानी से दिखाते हैं।

मेरे तीन कार्य हैं जो काफी हद तक समान हैं, लेकिन मुझे यह जानने में परेशानी होगी कि कौन-सा संकलन है और कौन-सा संकलन गैर-संकलनकर्ताओं को देगा।

सरल सामान्य कार्य:

fn only_borrow<T>(a: &mut T) {
    *a = *a;
}

परिणाम में त्रुटि:

error[E0507]: cannot move out of `*a` which is behind a mutable reference
 --> src/lib.rs:2:10
  |
2 |     *a = *a;
  |          ^^ move occurs because `*a` has type `T`, which does not implement the `Copy` trait

अप्रत्यक्ष के अतिरिक्त स्तर को शामिल करने से त्रुटि में परिवर्तन होता है

fn only_borrow_double<T>(a: &mut &mut T) {
    *a = *a;
}
error[E0623]: lifetime mismatch
 --> src/lib.rs:2:10
  |
1 | fn only_borrow_double<T>(a: &mut &mut T) {
  |                             -----------
  |                             |
  |                             these two types are declared with different lifetimes...
2 |     *a = *a;
  |          ^^ ...but data from `a` flows into `a` here

निहित जीवनकाल से दूर करने से त्रुटि ठीक हो सकती है:

fn working_double<'b, T>(a: &'b mut &'b mut T) {
    *a = *a;
}

जवाब

Emoun Aug 18 2020 at 09:59

आपको अपने जीवन काल पर एक नज़र डालनी होगी 'bऔर 'c:

  • &'b mut ...इसका मतलब है कि आपके पास एक संदर्भ है जो "समय" के लिए जीवित और मान्य है 'b
  • A<'c>इसका मतलब है कि आपके पास एक ऐसी वस्तु है जो जीवित है और जिसके लिए वैध है 'c

आपके पास जो नहीं है वह इन दो जन्मों के बीच एक विशिष्ट संबंध है। केवल एक चीज जो कंपाइलर काट सकता है वह यह है कि चूंकि A<'c>पीछे एक है &'b, तो 'cउसे आउटलाइव करना चाहिए 'b, यानी जब भी 'bवैध हो, ऐसा है 'c। हालांकि, महत्वपूर्ण रूप से, अन्य तरीके से नहीं।

आपको बताएंगे कि के रूप में, संकलक की आवश्यकता है 'bऔर 'cएक ही जीवन भर किया जाना है। ऐसा क्यों है?

आइए हम अपनी संभावनाओं पर एक नज़र डालें:

  1. 'cऔर 'bइसका कोई संबंध नहीं है: यह देखना आसान है कि किसी भी संबंध के बिना, संकलक इस बात की गारंटी नहीं दे सकता है कि इसमें क्या डाला गया है A.borrowऔर इस तरह यह अनुमति नहीं देगा।
  2. 'cकड़ाई से उल्लिखित 'b, यानी, कुछ स्थानों 'cको मान्य 'bनहीं है: जीवनकाल
    a.borrow = a.borrowका aउपयोग करने का एक पुनर्जन्म बन जाता है 'b। यह उत्तर बताता है कि ऐसा क्यों होता है । हालांकि, इसका मतलब है कि aअब 'bजीवनकाल पर निर्भर है , जो कि कुछ समय के aलिए मान्य नहीं है (चूंकि aजीवनकाल है 'c)। यह त्रुटि देता है।
  3. 'bकड़ाई से उल्लिखित 'c: यदि हमारे पास यह संबंध था, तो यह काम कर सकता है। रिबोर मान्य होगा, क्योंकि हमें एक "जीवन भर" ( 'b) की तुलना में हमने ( 'c) के लिए कहा है । हालांकि, हम पहले से ही 'c: 'bपर्दे के पीछे कंपाइलर से अनुमान लगा चुके हैं । इसलिए, इस जीवनकाल को जोड़ने का मतलब है कि दो जीवनकाल समान हो गए और हम फिर से वहीं हैं जहाँ हमने शुरू किया था:
struct A<'a> {
    borrow: &'a mut u8,
}

/// We add the relation 'b: 'c
fn does_nothing<'b: 'c, 'c>(a: &'b mut A<'c>) {
    a.borrow = a.borrow;
}