ICP·Devآی‌سی‌پی‌·دِو
بازگشت به مقالات
راست۱۰ تیر ۱۴۰۵4 دقیقه مطالعه

بالاخره «هرگز» فرا رسید: نگاهی به تلاش ده‌ساله راست برای پایدارسازی نوع !

پس از ده سال شوخی، شروع‌های ناموفق و بازنویسی‌های فشرده کامپایلر، «نوع هرگز» (never type یا !) در راست به مرحله نهایی پایدارسازی رسیده است. در این مطلب به بررسی موانع فنی، کدهای خطایاب (lints) و معنای این تغییر بزرگ برای امنیت نوع‌ها در راست ۱.۹۸ می‌پردازیم.

نکات کلیدی

  • پس از ده سال شوخی، شروع‌های ناموفق و بازنویسی‌های فشرده کامپایلر، «نوع هرگز» (never type یا !) در راست به مرحله نهایی پایدارسازی رسیده است
  • در این مطلب به بررسی موانع فنی، کدهای خطایاب (lints) و معنای این تغییر بزرگ برای امنیت نوع‌ها در راست ۱.۹۸ می‌پردازیم
اشتراک‌گذاری
بالاخره «هرگز» فرا رسید: نگاهی به تلاش ده‌ساله راست برای پایدارسازی نوع !

بالاخره «هرگز» فرا رسید: نگاهی به تلاش ده‌ساله راست برای پایدارسازی نوع !

پایان یک شوخی ده‌ساله

«نوع هرگز بر اساس تاریخ پایدارسازی‌اش نام‌گذاری شده است» نزدیک به یک دهه شوخی محبوب و خودانتقادانه‌ای در جامعه کاربری راست بوده است. اولین بار در سال ۲۰۱۵ طی یک RFC معرفی شد و از سال ۲۰۱۶ در ایشوی شماره ۳۵۱۲۱ گیت‌هاب ردیابی می‌شود (و با علامت تعجب ! نشان داده می‌شود)، این نوع بی‌عضو (uninhabited) همواره دور از دسترس به نظر می‌رسید. این نوع در سال ۲۰۱۹ در راست ۱.۴۱ پایدار شد، اما بلافاصله به دلیل بروز پس‌رفت‌های شدید در سازگاری عقب‌رو (backward-compatibility) لغو شد و به هدف دست‌نیافتنی تیم کامپایلر تبدیل گشت.

اکنون این انتظار رو به پایان است. به دنبال تلاش فشرده و همه‌جانبه جامعه کاربری در طول سال ۲۰۲۵ و اوایل ۲۰۲۶، پول ریکوئست رسمی برای پایدارسازی نوع هرگز سرانجام وارد «مرحله نهایی نظرات» (FCP) شده است. اگر این مانع نهایی بدون بازگشت برطرف شود، نوع هرگز به صورت پیش‌فرض در راست ۱.۹۸.۰ ارائه خواهد شد که انتشار آن برای ۲۰ اوت ۲۰۲۶ برنامه‌ریزی شده است.

نوع هرگز (!) چیست و چرا اهمیت دارد؟

در تئوری نوع‌ها، ! یک نوع پایین (bottom type) یا نوع بی‌عضو (uninhabited type) است. این یعنی نماینده نوعی است که دقیقاً صفر مقدار معتبر در زمان اجرا دارد؛ شما هرگز نمی‌توانید نمونه‌ای از آن بسازید.

اگر یک نوع نمی‌تواند وجود داشته باشد، چرا باید آن را در کدهایمان بخواهیم؟ پاسخ در جریان کنترل (control flow) نهفته است. بسیاری از محاسبات در راست در واقع هرگز مقداری را برنمی‌گردانند. به عنوان مثال:

  • تابع std::process::exit(code) بلافاصله از برنامه خارج می‌شود.
  • ماکروی panic!("...") اجرای ترد را متوقف می‌کند.
  • یک حلقه بی‌پایان loop {} تا ابد اجرا می‌شود مگر اینکه متوقف شود.
  • عبارت‌های جریان کنترل مانند break، continue و return بلاک فعلی را سقط (abort) می‌کنند.

در پشت صحنه، تمامی این عبارت‌ها نوع ! را برمی‌گردانند. از آنجایی که ! نشان‌دهنده یک مسیر کنترلی است که هرگز مقداری تولید نمی‌کند، کامپایلر اجازه می‌دهد تا ! به طور ضمنی به هر نوع دیگری تبدیل (coerce) شود. این ویژگی منجر به ایجاد APIهای بسیار زیبا و ایمن از نظر نوع می‌شود:

rust
let value: u32 = match get_number() {
    Some(num) => num,
    None => panic!("Oh no!"), // نوع ! را برمی‌گرداند که به u32 تبدیل می‌شود
};

از آنجا که شاخه None واگرا می‌شود، کامپایلر می‌داند در صورت ادامه اجرا، مقدار value تضمین شده است که یک u32 معتبر باشد. این امر نیاز به مقادیر پیش‌فرض ساختگی یا تبدیل‌های ناامن اشاره‌گر (unsafe pointer casts) را از بین می‌برد.

یک نمودار مدرن و دقیق که سیستم نوع راست را نشان می‌دهد...

مانع فنی: تله جایگزینی با ()

اگر ! این‌قدر مفید است و از قبل به صورت ضمنی وجود داشته، چرا پایدارسازی آن ده سال طول کشیده است؟

پاسخ در پشتیبان استنتاج نوع (type inference fallback) نهفته است. در گذشته، اگر کامپایلر با یک تبدیل نوع مبهم مواجه می‌شد که شامل ! بود، به یک هک قدیمی متوسل می‌شد: استفاده از نوع خالی (unit type یا ()) به عنوان جایگزین. سال‌ها این جایگزینی خطاهای نوع را پنهان می‌کرد، اما با تکامل سیستم نوع راست، این جایگزینی ضمنی شروع به ایجاد باگ‌های درستی‌پذیری (soundness) و خراب کردن بلاک‌های ناامن (unsafe blocks) کرد.

تبدیل ! به یک نوع درجه‌اول واقعی و مستقل به معنای تغییر این رفتار جایگزینی بود تا به جای ()، به طور پیش‌فرض از ! استفاده کند. انجام این کار بلافاصله صدها کریت (crate) قدیمی در crates.io را که ناخودآگاه به جایگزینی با () متکی بودند، خراب می‌کرد.

تیم کامپایلر چگونه این بن‌بست را شکست؟

برای حل این بن‌بست، توسعه‌دهنده کامپایلر معروف به "Waffle" و مابقی اعضای تیم راست، دو سال گذشته را صرف اجرای یک استراتژی منسوخ‌سازی (deprecation) دقیق و گام‌به‌گام کردند.

در راست ۱.۹۲.۰ (منتشر شده در اواخر سال ۲۰۲۵)، تیم توسعه دو هشدار خطایاب (lint) حیاتی را به حالت پیش‌فرض-ممنوع (deny-by-default) تغییر داد:

  1. never_type_fallback_flowing_into_unsafe
  2. dependency_on_unit_never_type_fallback

این هشدارها نگهداران کریت‌ها را مجبور کرد تا به جای تکیه بر جایگزینی ضمنی ()، ابهام نوع را به طور صریح مدیریت کنند.

در کنفرانس RustWeek 2026 در اوترخت، Waffle ارائه برجسته‌ای به نام «چه زمانی هرگز است؟» داشت و در آن تشریح کرد که چگونه این چرخه‌های خطایابی به صورت سیستماتیک اکوسیستم را از وابستگی‌های قدیمی جایگزینی پاک‌سازی کردند. با رفع این موانع، مشکلات درستی‌پذیری سیستم نوع که باعث عقب‌گرد سال ۲۰۱۹ شده بودند، بالاخره حل شده‌اند.

آغاز عصر راست ۱.۹۸.۰

با قرار گرفتن پول ریکوئست پایدارسازی در مرحله نهایی نظرات، توسعه‌دهندگان راست خود را برای آینده‌ای تمیزتر آماده می‌کنند. به زودی، Infallible (اینام خالی که برای نتایجی که هرگز با شکست مواجه نمی‌شوند استفاده می‌شود) یک نام مستعار مستقیم برای ! خواهد بود و توسعه‌دهندگان در نهایت قادر خواهند بود از ! در امضاهای عمومی API بدون نیاز به فعال‌سازی ویژگی‌های nightly استفاده کنند.

اگرچه این ده سال طراحی کامپایلر طولانی و طاقت‌فرسا بود، اما راست ۱.۹۸.۰ ثابت می‌کند تعهد این زبان به امنیت، پیش‌بینی‌پذیری و درستی‌پذیری تغییرناپذیر است. دیر رسیدن بهتر از هرگز نرسیدن است – یا در مورد راست، هر دو!

برچسب‌ها

#راست#راست ۱.۹۸#سیستم نوع‌ها#کامپایلر#برنامه‌نویسی

منابع و ارجاعات مستند

پیشنهاد مطالعه بعدی

خوشتان آمد؟ مقاله بعدی را بگیرید

در خبرنامه عضو شوید تا راهنمای بعدی در ایمیلتان باشد — بدون مزاحمت، لغو عضویت در هر زمان.