एक दूसरे निहितार्थ को जोड़कर तर्क की बौखलाहट को रोका क्यों जाता है?


10

मैं इस मुद्दे पर आया जब Add<char> for Stringमानक पुस्तकालय में निहित जोड़ने की कोशिश कर रहा था । लेकिन हम इसे आसानी से दोहरा सकते हैं, ऑपरेटर शेंनिगन के बिना। हम इसके साथ शुरू करते हैं:

trait MyAdd<Rhs> {
    fn add(self, rhs: Rhs) -> Self;
}

impl MyAdd<&str> for String {
    fn add(mut self, rhs: &str) -> Self {
        self.push_str(rhs);
        self
    }
}

काफी सरल। इसके साथ, निम्नलिखित कोड संकलित करता है:

let a = String::from("a");
let b = String::from("b");
MyAdd::add(a, &b);

ध्यान दें कि इस मामले में, दूसरी तर्क अभिव्यक्ति ( &b) का प्रकार है &String। यह तो deref-coerced में &strऔर फ़ंक्शन कॉल कार्य करता है।

हालाँकि , चलिए निम्नलिखित जोड़ जोड़ने का प्रयास करते हैं:

impl MyAdd<char> for String {
    fn add(mut self, rhs: char) -> Self {
        self.push(rhs);
        self
    }
}

( खेल के मैदान पर सब कुछ )

अब MyAdd::add(a, &b)उपरोक्त अभिव्यक्ति निम्नलिखित त्रुटि की ओर ले जाती है:

error[E0277]: the trait bound `std::string::String: MyAdd<&std::string::String>` is not satisfied
  --> src/main.rs:24:5
   |
2  |     fn add(self, rhs: Rhs) -> Self;
   |     ------------------------------- required by `MyAdd::add`
...
24 |     MyAdd::add(a, &b);
   |     ^^^^^^^^^^ the trait `MyAdd<&std::string::String>` is not implemented for `std::string::String`
   |
   = help: the following implementations were found:
             <std::string::String as MyAdd<&str>>
             <std::string::String as MyAdd<char>>

ऐसा क्यों है? मेरे लिए ऐसा लगता है कि डेरेफ़-ज़बरदस्ती केवल तब की जाती है जब केवल एक फ़ंक्शन उम्मीदवार होता है। लेकिन यह मुझे गलत लगता है। नियम ऐसे क्यों होंगे? मैंने विनिर्देशन के माध्यम से देखने की कोशिश की, लेकिन मुझे तर्क के डर पर कुछ भी नहीं मिला है।


यह मुझे इस उत्तर की याद दिलाता है (मैंने लिखा था)। संकलक गुण को उदारता से जानता है, और जब केवल एक ही implलागू होता है, तो इसमें उपयोग किए गए प्रकार के तर्क को चुनकर इसे खंडित किया जा सकता है impl। अन्य प्रश्नोत्तर में मैंने implकॉल करने के लिए कंपाइलर (दिखने) के लिए इस क्षमता का उपयोग किया , जो आमतौर पर ऐसा कुछ होता है। संभवत: इस मामले में यह वही है जो इसे डेरेफ़ ज़बरदस्ती करने की अनुमति देता है। लेकिन यह केवल एक अनुमान है।
ट्रेंटक्ल

2
यहां एक टिप्पणी है जिसमें कहा गया है कि यदि केवल एक प्रत्यारोपण को संकलक "उत्सुकता से पुष्टि करता है" पाया जाता है, जो कि डेरेफ़ कोअर्चेन्स (अन्य चीजों के बीच) होने की अनुमति देता है। यह एक से अधिक उम्मीदवारों के लिए नहीं होता है। इसलिए मुझे लगता है कि यह उत्तर की तरह है, लेकिन मैं और अधिक जानने के लिए प्यार करना चाहूंगा। जंग किताब में यह अध्याय मदद कर सकता है, लेकिन जहाँ तक मैं बता सकता हूँ, यह विशेष रूप से इस बारे में कुछ नहीं कहता है।
लुकास कालबर्टोड 16

जवाबों:


0

जैसा कि आपने स्वयं समझाया, संकलक उस स्थिति का इलाज करता है, जहाँ केवल एक ही वैध है impl, और इसका उपयोग ड्राइव प्रकार की अस्वीकृति के लिए कर सकते हैं:

यहां एक टिप्पणी है जिसमें कहा गया है कि यदि केवल एक प्रत्यारोपण को संकलक "उत्सुकता से पुष्टि करता है" पाया जाता है, जो कि डेरेफ़ कोअर्शन (अन्य चीजों के बीच) होने की अनुमति देता है। यह एक से अधिक उम्मीदवारों के लिए नहीं होता है।

दूसरा हिस्सा यह है कि डेरेफ़ ज़बरदस्ती केवल उन साइटों पर होगी जहां अपेक्षित प्रकार ज्ञात है, यह सट्टा नहीं होता है। संदर्भ में जबरदस्ती साइटें देखें । Impl चयन और प्रकार का अनुमान पहले स्पष्ट रूप से लगता है कि MyAdd::add(&str)उम्मीद की जानी चाहिए, करने के लिए तर्क का प्रयास करने के लिए &str

यदि इस स्थिति में वर्कअराउंड की आवश्यकता है, तो दूसरे तर्क की तरह &*bया &b[..]उसके b.as_str()लिए एक अभिव्यक्ति का उपयोग करें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.