2016-06-25 3 views
9

मुझे लगातार संकलन त्रुटि मिली है जहां जंग ने शिकायत की है कि मेरे पास एक अपरिवर्तनीय उधार है जबकि मैं उत्परिवर्ती उधार लेने की कोशिश कर रहा हूं, लेकिन अपरिवर्तनीय उधार दूसरे दायरे से है, और मैं इससे कुछ भी नहीं ला रहा हूं।हैश मैप का जंग उधार उस दायरे से बाहर रहता है जो इसमें है?

मेरे पास कुछ कोड है जो मानचित्र में किसी मान के लिए जांच करता है, और यदि यह मौजूद है, तो इसे वापस कर दें, अन्यथा इसे मानचित्र को विभिन्न तरीकों से बदलना होगा। समस्या यह है कि मुझे लगता है कि जंग को पाने के लिए मुझे कोई रास्ता नहीं मिल रहा है, भले ही दोनों ऑपरेशन पूरी तरह से अलग हों। साथ बाहर

fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> { 
    // extra scope in vain attempt to contain the borrow 
    { 
     match map.get(&key) { // borrow immutably 
      Some(key) => { return Some(key); }, 
      None =>(), 
     } 
    } 

    // now I'm DONE with the immutable borrow, but rustc still thinks it's borrowed 

    map.insert(0, 0); // borrow mutably, which errors 
    None 
} 

यह त्रुटियों:

error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable 
    --> src/main.rs:17:5 
    | 
7 |   match map.get(&key) { // borrow immutably 
    |    --- immutable borrow occurs here 
... 
17 |  map.insert(0, 0); // borrow mutably, which errors 
    |  ^^^ mutable borrow occurs here 
18 |  None 
19 | } 
    | - immutable borrow ends here 

यह मेरे लिए कोई मतलब नहीं है

यहाँ कुछ अतर्कसंगत कोड है कि मेरे कोड के रूप में ही संरचना इस प्रकार है और समस्या को दर्शाती है। अपरिवर्तनीय उधार उस दायरे को कैसे बढ़ाता है ?! उस match की एक शाखा रिटर्न के माध्यम से फ़ंक्शन से बाहर निकलती है, और दूसरा कुछ भी नहीं करता है और दायरा छोड़ देता है।

मैंने ऐसा देखा है कि मैं गलती से किसी अन्य चर में दायरे से उधार ले रहा था, लेकिन यह मामला यहां नहीं है!

सच है, उधार रिटर्न स्टेटमेंट के माध्यम से दायरे से बच रहा है, लेकिन यह हास्यास्पद है कि फ़ंक्शन में आगे उधार लेने वाले ब्लॉक - कार्यक्रम संभवतः वापस नहीं आ सकता है और जारी रख सकता है! अगर मैं वहां कुछ और लौटाता हूं, तो त्रुटि दूर हो जाती है, इसलिए मुझे लगता है कि उधारकर्ता चेकर लटका रहा है। यह मुझे एक बग की तरह लगता है।

दुर्भाग्यवश, मैं एक ही त्रुटि को मारने के बिना इसे फिर से लिखने का कोई तरीका नहीं ढूंढ पाया, इसलिए यदि यह मामला है तो यह विशेष रूप से खराब बग है।

+0

दुर्भाग्य से, .entry() इस समारोह क्या करने की जरूरत के लिए सही नहीं है। मुझे गैर-अक्षीय स्कॉप्स मुद्दे के बारे में पता है, और आमतौर पर मैं इसके आसपास काम कर सकता हूं, लेकिन इस मामले में, मैं ऐसी चीज के साथ आने में सक्षम नहीं हूं जो डुप्लीकेट काम का गुच्छा नहीं करता है, इससे कोई फर्क नहीं पड़ता कि कैसे बदसूरत कामकाज है ... आमतौर पर इस मुद्दे के आसपास एक गुंजाइश काम भी जोड़ता है, लेकिन यहां यह नहीं है; यहां तक ​​कि एक उधार को दूसरे कार्य में ले जाने से भी मदद नहीं मिलती है। –

उत्तर

6

यह known issue है जो non-lexical scopes द्वारा हल किया जाने की संभावना है, जो स्वयं MIR पर अनुमानित है। यदि ऐसा होता है कि आप उसी कुंजी पर डाल रहे हैं जिसे आप देख रहे हैं, तो मैं आपको use the entry API पर प्रोत्साहित करता हूं।

अब आप इसके लिए काम करने के लिए अक्षमता का एक स्मिडजेन जोड़ सकते हैं। सामान्य विचार एक बुलियन जोड़ना है जो आपको बताता है कि कोई मूल्य मौजूद था या नहीं। एक HashMap के बजाय एक वेक्टर के साथ

use std::collections::BTreeMap; 

fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> { 
    if map.contains_key(&key) { 
     return map.get(&key); 
    } 

    map.insert(0, 0); 
    None 
} 

fn main() { 
    let mut map = BTreeMap::new(); 
    do_stuff(&mut map, 42); 
    println!("{:?}", map) 
} 

इसी तरह के मामलों संदर्भ की बजाय तत्व के सूचकांक का उपयोग करके हल किया जा सकता: यह बूलियन एक संदर्भ के लिए पर लटका नहीं है, इसलिए कोई उधार है। ऊपर दिए गए मामले की तरह, यह स्लाइस सीमाओं को फिर से जांचने की आवश्यकता के कारण कुछ अक्षमता पेश कर सकता है।

fn find_or_create_five<'a>(container: &'a mut Vec<u8>) -> &'a mut u8 { 
    match container.iter_mut().find(|e| **e == 5) { 
     Some(element) => element, 
     None => { 
      container.push(5); 
      container.last_mut().unwrap() 
     } 
    } 
} 

के बजाय आप लिख सकते हैं

:

fn find_or_create_five<'a>(container: &'a mut Vec<u8>) -> &'a mut u8 { 
    let idx = container.iter().position(|&e| e == 5).unwrap_or_else(|| { 
     container.push(5); 
     container.len() - 1  
    }); 
    &mut container[idx] 
} 

ध्यान दें कि गैर शाब्दिक जीवन काल पर काम किया जा रहा है।हर रात को जंग में, दोनों मूल कोड उदाहरण संकलन के रूप में है, जब NLL सक्षम है:

#![feature(nll)] 

use std::collections::BTreeMap; 

fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> { 
    if let Some(key) = map.get(&key) { 
     return Some(key); 
    } 

    map.insert(0, 0); 
    None 
} 
#![feature(nll)] 

fn find_or_create_five(container: &mut Vec<u8>) -> &mut u8 { 
    match container.iter_mut().find(|e| **e == 5) { 
     Some(element) => element, 
     None => { 
      container.push(5); 
      container.last_mut().unwrap() 
     } 
    } 
} 
संबंधित मुद्दे