2017-10-19 32 views
14

n1_mut अभी भी इस उदाहरण में मान्य क्यों है? इसे Option::Some में स्थानांतरित कर दिया गया है, इसलिए यह अमान्य नहीं होना चाहिए?पॉइंटर के किसी सदस्य को असाइन करना क्यों पॉइंटर स्थानांतरित होने के बाद भी मान्य है?

struct MyRecordRec2<'a> { 
    pub id: u32, 
    pub name: &'a str, 
    pub next: Box<Option<MyRecordRec2<'a>>> 
} 

#[test] 
fn creating_circular_recursive_data_structure() { 
    let mut n1_mut = MyRecordRec2 { 
     id: 1, 
     name: "n1", 
     next: Box::new(None) 
    }; 

    let n2 = MyRecordRec2 { 
     id: 2, 
     name: "n2", 
     next: Box::new(Some(n1_mut)) 
    }; 

    //Why is n1_mut still valid? 
    n1_mut.next = Box::new(Some(n2)); 
} 

निम्नलिखित परिचित "चले गए मूल्य के उपयोग" के साथ संकलन नहीं करता त्रुटि:

#[test] 
fn creating_and_freezing_circular_recursive_data_structure() { 
    let loop_entry = { 
     let mut n1_mut = MyRecordRec2 { 
      id: 1, 
      name: "n1", 
      next: Box::new(None), 
     }; 

     let n2 = MyRecordRec2 { 
      id: 2, 
      name: "n2", 
      next: Box::new(Some(n1_mut)), 
     }; 

     n1_mut.next = Box::new(Some(n2)); 

     n1_mut 
    }; 
} 
error[E0382]: use of moved value: `n1_mut` 
    --> src/main.rs:44:9 
    | 
39 |    next: Box::new(Some(n1_mut)), 
    |         ------ value moved here 
... 
44 |   n1_mut 
    |   ^^^^^^ value used here after move 
    | 
    = note: move occurs because `n1_mut` has type `MyRecordRec2<'_>`, which does not implement the `Copy` trait 
+0

दिलचस्प। सुनिश्चित नहीं है कि यह एक बग के रूप में गिना जाता है - मुझे नहीं लगता कि आप असुरक्षित प्रेरित कर सकते हैं क्योंकि बाद में स्मृति को पढ़ने का कोई तरीका नहीं है। लेकिन अगर आप स्टैक पर कच्चे पॉइंटर रखते हैं तो आप बता सकते हैं कि 'n1Mut.next' वास्तव में सेट हो जाता है: https://play.rust-lang.org/?gist=d414orgianfd142c289667e7c2fb3183be0&version=undefined – trentcl

+0

दिलचस्प बात यह है कि यहां तक ​​कि संभव नहीं है के बाद 'n1_mut.next' का उपयोग करें। साथ ही, 'ड्रॉप' कार्यान्वयन को जोड़ने का कारण बनता है: "त्रुटि [E0383]: अनियमित संरचना का आंशिक पुनर्नवीनीकरण 'n1_mut'" –

उत्तर

8

यह एक सूचक या नहीं किया जा रहा से कोई लेना देना नहीं है, इस रूप में अच्छी तरह से काम करता है:

#[derive(Debug)] 
struct NonCopy; 

#[derive(Debug)] 
struct Example { 
    name: NonCopy, 
} 

fn main() { 
    let mut foo = Example { 
     name: NonCopy, 
    }; 

    drop(foo); 

    foo.name = NonCopy; 
} 

हालांकि मैं समान तो सवाल यह मुझे पता है कि मैं पहले देखा है, नहीं मिल सकता है इस quote from nikomatsakis यह वर्णन करता है:

In general moves are tracked at a pretty narrow level of granularity. We intend to eventually permit you to "fill" both fields back in and then use the structure again. I guess that doesn't work today. I have to go look again at the moves code, but I think in general one of the things I'd like to pursue post 1.0 is extending the type system to deal better with things that have been moved from (in particular I want to support moves out of &mut pointers, so long as you restore the value before doing anything fallible). Anyway I think this example more-or-less falls out of treating things in a general way, though you could imagine rules that say "if you move f, you can never again touch any subfields of f without restoring f as a unit".

वहाँ भी, the Rust subreddit पर चर्चा है जो जंग के लिए लिंक issue 21232: "borrow-checker allows partial reinit of struct that has been moved away, but no use of it"

संकल्पनात्मक रूप से, संरचना के अलावा संरचना में प्रत्येक फ़ील्ड के लिए एक ध्वज है - मुझे Chris Morgan's cardboard box analogy के बारे में सोचना पसंद है। आप struct उपयोग करने से पहले इतने लंबे समय के रूप में आप में वापस ले जाने के लिए एक स्वामित्व struct के क्षेत्र से बाहर स्थानांतरित कर सकते हैं:

drop(foo.name); 
foo.name = NonCopy; 

println!("{:?}", foo); 
जाहिर

, 2014 के बाद से, कोई भी वैध के रूप में पूरे struct अंकन सक्षम करने के लिए प्रयास करना परेशान है एक बार खेतों को फिर से भरने के बाद।

वास्तव में, आपको वास्तव में इस कार्यक्षमता की आवश्यकता नहीं है क्योंकि आप केवल एक ही चर को एक ही समय में असाइन कर सकते हैं। वर्तमान कार्यान्वयन अत्यधिक सुरक्षित है क्योंकि जंग आपको कुछ ऐसा करने से रोक रही है जो ठीक लगता है।

संबंधित मुद्दे