উচ্চ-র‌্যাঙ্কযুক্ত বৈশিষ্ট্য সীমানায় কেন closure std :: میم :: ড্রপ বন্ধের মতো নয়? _ | ()?


13

বাস্তবায়ন std::mem::dropনিম্নলিখিত হিসাবে নথিভুক্ত করা হয়:

pub fn drop<T>(_x: T) { }

এই হিসাবে, আমি আশা করব বন্ধ |_| ()( উভয় দিক থেকে টয়লেট ক্লোজার হিসাবে পরিচিত ) সম্ভাব্য 1: 1 প্রতিস্থাপন হবে drop, উভয় দিকেই। তবে নীচের কোডগুলি দেখায় যে dropফাংশনের প্যারামিটারে আবদ্ধ উচ্চতর র‌্যাঙ্কযুক্ত বৈশিষ্ট্যের সাথে সামঞ্জস্যপূর্ণ নয়, যেখানে টয়লেট বন্ধ রয়েছে।

fn foo<F, T>(f: F, x: T)
where
    for<'a> F: FnOnce(&'a T),
{
    dbg!(f(&x));
}

fn main() {
    foo(|_| (), "toilet closure"); // this compiles
    foo(drop, "drop"); // this does not!
}

সংকলকের ত্রুটি বার্তা:

error[E0631]: type mismatch in function arguments
  --> src/main.rs:10:5
   |
1  | fn foo<F, T>(f: F, x: T)
   |    ---
2  | where
3  |     for<'a> F: FnOnce(&'a T),
   |                ------------- required by this bound in `foo`
...
10 |     foo(drop, "drop"); // this does not!
   |     ^^^
   |     |
   |     expected signature of `for<'a> fn(&'a _) -> _`
   |     found signature of `fn(_) -> _`

error[E0271]: type mismatch resolving `for<'a> <fn(_) {std::mem::drop::<_>} as std::ops::FnOnce<(&'a _,)>>::Output == ()`
  --> src/main.rs:10:5
   |
1  | fn foo<F, T>(f: F, x: T)
   |    ---
2  | where
3  |     for<'a> F: FnOnce(&'a T),
   |                ------------- required by this bound in `foo`
...
10 |     foo(drop, "drop"); // this does not!
   |     ^^^ expected bound lifetime parameter 'a, found concrete lifetime

যে dropকোনও আকারের ক্ষেত্রে শ্রদ্ধার সাথে জেনেরিক বলে বিবেচনা করে T, এটি "আরও জেনেরিক" স্বাক্ষরের fn(_) -> _সাথে সামঞ্জস্যপূর্ণ নয় এমনটি অযৌক্তিক বলে মনে হয় for<'a> fn (&'a _) -> _। সংকলকটি কেন dropএখানে স্বাক্ষর স্বীকার করছে না এবং টয়লেট বন্ধ হওয়ার স্থানে রাখলে কী আলাদা হয়?

উত্তর:


4

ইস্যুটির মূলটি হ'ল এটি dropএকটি একক ফাংশন নয়, বরং একটি প্যারামিটারাইজাইজড ফাংশনগুলির সেট যা প্রতিটি নির্দিষ্ট কিছু প্রকার ড্রপ করে। উচ্চ-র‌্যাঙ্কযুক্ত বৈশিষ্ট্য সীমানা (পরবর্তীকালে এইচআরটিবি) পূরণ করার জন্য আপনার একক ফাংশন প্রয়োজন যা একই সাথে কোনও নির্দিষ্ট জীবনকাল সহ কোনও প্রকারের রেফারেন্স নিতে পারে।


আমরা dropএকটি জেনেরিক ফাংশনের সাধারণ উদাহরণ হিসাবে ব্যবহার করব , তবে এগুলি আরও সাধারণভাবে প্রযোজ্য। এখানে উল্লেখের জন্য কোড আছে: fn drop<T>(_: T) {}

ধারণামূলকভাবে, dropএকটি একক ফাংশন নয়, বরং প্রতিটি সম্ভাব্য ধরণের জন্য একটি ফাংশন T। যে কোনও নির্দিষ্ট উদাহরণ dropকেবল একটি একক ধরণের আর্গুমেন্ট গ্রহণ করে। একে মনোমরফাইজেশন বলা হয় । যদি এর Tসাথে আলাদা ব্যবহার করা হয় তবে এর dropএকটি আলাদা সংস্করণ dropসংকলিত হয়। এজন্য আপনি জেনেরিক ফাংশনটি আর্গুমেন্ট হিসাবে পাস করতে পারবেন না এবং সেই ফাংশনটি পুরো সাধারণতায় ব্যবহার করতে পারবেন না ( এই প্রশ্নটি দেখুন )

অন্যদিকে, fn pass(x: &i32) -> &i32 {x}এইচআরটিবি সন্তুষ্ট করার মতো একটি ফাংশন for<'a> Fn(&'a i32) -> &'a i32। বিপরীতে drop, আমাদের একটি একক ফাংশন রয়েছে যা একই সাথে প্রতিটি জীবনকালের Fn(&'a i32) -> &'a i32জন্য সন্তুষ্ট হয় । এটি কীভাবে ব্যবহার করা যায় তা প্রতিফলিত হয় ।'apass

fn pass(x: &i32) -> &i32 {
    x
}

fn two_uses<F>(f: F)
where
    for<'a> F: Fn(&'a i32) -> &'a i32, // By the way, this can simply be written
                                       // F: Fn(&i32) -> &i32 due to lifetime elision rules.
                                       // That applies to your original example too.
{
    {
        // x has some lifetime 'a
        let x = &22;
        println!("{}", f(x));
        // 'a ends around here
    }
    {
        // y has some lifetime 'b
        let y = &23;
        println!("{}", f(y));
        // 'b ends around here
    }
    // 'a and 'b are unrelated since they have no overlap
}

fn main() {
    two_uses(pass);
}

(খেলার মাঠ)

উদাহরণস্বরূপ, জীবনকাল 'aএবং 'bএকে অপরের সাথে কোনও সম্পর্ক নেই: একে অপরকে সম্পূর্ণ পরিবেষ্টিত করে না। সুতরাং এখানে কোন ধরণের সাব টাইপিং জিনিস চলছে না। এর একক উদাহরণ passসত্যই দুটি পৃথক, সম্পর্কযুক্ত জীবনকাল সহ ব্যবহার করা হচ্ছে।

এই কারণেই dropসন্তুষ্ট হয় না for<'a> FnOnce(&'a T)। যে কোনও নির্দিষ্ট উদাহরণ dropকেবল একটি জীবনকালকে আবরণ করতে পারে (সাব-টাইপিং উপেক্ষা করে)। আমরা যদি পাস dropমধ্যে two_uses(অসম্মান স্বাক্ষর পরিবর্তন এবং অভিমানী কম্পাইলার চল সঙ্গে) উপরোক্ত উদাহরণে থেকে, এটা কিছু বিশেষ জীবনকাল চয়ন করতে হবে 'aএবং দৃষ্টান্ত dropসুযোগ two_usesহবে Fn(&'a i32)কিছু কংক্রিট জীবদ্দশায় 'a। যেহেতু ফাংশনটি কেবল একক আজীবনের জন্য প্রযোজ্য 'aতাই দুটি সম্পর্কযুক্ত জীবনকাল সহ এটি ব্যবহার করা সম্ভব হবে না।

তাহলে টয়লেট বন্ধ কেন এইচআরটিবি পাবে? বন্ধের জন্য প্রকারটি অনুমান করার সময়, যদি প্রত্যাশিত প্রকারটি যদি উচ্চ স্তরের বৈশিষ্ট্যযুক্ত বাউন্ডের প্রয়োজন হয় এমন ইঙ্গিত দেয় তবে সংকলকটি একটি ফিট করার চেষ্টা করবে । এই ক্ষেত্রে, এটি সফল হয়।


ইস্যু # 41078 এর সাথে ঘনিষ্ঠভাবে জড়িত এবং বিশেষত, এখানে এডিবির মন্তব্যটি মূলত উপরের ব্যাখ্যাটি দেয় (যদিও সাধারণ ফাংশনগুলির চেয়ে ক্লোজারের প্রসঙ্গে)। যদিও ইস্যুটি নিজেই বর্তমান সমস্যার সমাধান করে না। পরিবর্তে এটি ব্যবহার করার আগে আপনি যদি কোনও ভেরিয়েবলের জন্য টয়লেট বন্ধ করার বিষয়টি নির্ধারণ করেন তবে এটি কী হবে তা সম্বোধন করে (এটি চেষ্টা করে দেখুন!)।

ভবিষ্যতে পরিস্থিতি পরিবর্তিত হতে পারে এটি সম্ভব, তবে জেনেরিক ফাংশনগুলি কীভাবে মনোবিশ্লেষিত হয় তাতে একটি বড় পরিবর্তন দরকার।


4

সংক্ষেপে, উভয় লাইন ব্যর্থ হওয়া উচিত। তবে যেহেতু এইচআরটিবি লাইফটাইমগুলি হ্যান্ডেল করার পুরানো পদ্ধতিতে এক পদক্ষেপ, যথা লিক চেক , বর্তমানে কিছুটা দৃ .়তার সমস্যা রয়েছে, rustcশেষ হয়েছে (ভুলভাবে) একজনকে গ্রহণ করা এবং অন্যটিকে খুব খারাপ ত্রুটির বার্তা দিয়ে রেখে দেওয়া।

আপনি যদি এর সাথে ফাঁস চেকটি অক্ষম করেন rustc +nightly -Zno-leak-check, আপনি আরও বুদ্ধিমান ত্রুটি বার্তাটি দেখতে সক্ষম হবেন:

error[E0308]: mismatched types
  --> src/main.rs:10:5
   |
10 |     foo(drop, "drop");
   |     ^^^ one type is more general than the other
   |
   = note: expected type `std::ops::FnOnce<(&'a &str,)>`
              found type `std::ops::FnOnce<(&&str,)>`

আমার এই ত্রুটিটির ব্যাখ্যাটি হ'ল ফাংশনটির &xমূল অংশটি fooকেবলমাত্র বডিটির মধ্যে আবদ্ধ থাকে, f(&x)একইভাবে একই আকাশকালীন জীবনকালও রয়েছে যা সম্ভবত for<'a>বৈশিষ্ট্যের দ্বারা আবদ্ধ সার্বজনীন পরিমাণকে পূরণ করতে পারে না ।

আপনি এখানে যে প্রশ্নটি উপস্থাপন করছেন তা # 57642 ইস্যু করার প্রায় একইরকম , যার দুটি বিপরীত অংশ রয়েছে।

এইচআরটিবি লাইফটাইম প্রক্রিয়া করার নতুন উপায় হ'ল তথাকথিত মহাবিশ্বগুলি ব্যবহার করে । মহাবিশ্বের সাথে ফুটো চেক মোকাবেলায় নিকোর একটি ডাব্লুআইপি রয়েছে । এই নতুন শাসনামলে, উপরের লিঙ্কযুক্ত # 57642 ইস্যুটির উভয় অংশই আরও বেশি স্পষ্ট নির্ণয়ের সাথে সমস্ত ব্যর্থ বলেছে । আমি মনে করি যে সংকলকটি তখনও আপনার উদাহরণ কোডটি সঠিকভাবে পরিচালনা করতে সক্ষম হবে should

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.