ورژن جدید راست - Rust 1.98.0 منتشر شد: متدهای جبری برای اعشاریها و جایگزین رسمی برای crate معروف itoa
حدود ۵ دقیقه مطالعه
تیم Rust، بیستم آگوست، نسخهی 1.98.0 رو منتشر کرد. ویژگی اصلی این نسخه، متدهای جدید «جبری» (algebraic) برای انواع اعشاریه که امکان بهینهسازیهای تهاجمیتر روی محاسبات ریاضی رو فراهم میکنه؛ در کنار چند تا API پایدارشدهی دیگه که مستقیم رو کد روزمره تأثیر میذارن.
متدهای جبری: چیزی شبیه -ffast-math
انواع f32 و f64 حالا متدهای جدیدی برای جمع، تفریق، ضرب، تقسیم، و باقیمونده دارن که با پیشوند «algebraic» شناخته میشن (مثل algebraic_add). این متدها به کامپایلر اجازه میدن از خاصیتهای جبری اعداد حقیقی برای بهینهسازی استفاده کنه، حتی اگه این خاصیتها بهخاطر محدودیتهای نمایش اعشاری (floating-point) دقیقاً برقرار نباشن.
نکتهی مهم اینه که مجموعهی دقیق این بهینهسازیها مشخص نشده، ولی میتونه شبیه چیزی باشه که با فلگ -ffast-math تو زبونها و کامپایلرهای دیگه میبینی. مثلاً جمع اعشاری معمولی associative نیست؛ یعنی a + b + c + d باید دقیقاً به همون ترتیب چپبهراستی که parse شده محاسبه بشه: ((a + b) + c) + d. متدهای algebraic این محدودیت رو کنار میذارن و به کامپایلر اجازه میدن ترتیب محاسبه رو برای سرعت بیشتر عوض کنه.
طبق بحثهای جامعه (از جمله رو Lobsters)، این بهینهسازی محدود به عبارتهای ریاضی طولانی نمیشه؛ حلقههایی که یه مقدار رو بهصورت تجمعی جمع میزنن (مثل total += item تو یه loop) هم میتونن از این متدها سود ببرن، چون کامپایلر میتونه loop رو vectorize کنه؛ چیزی که با عملگرهای معمولی += (بهخاطر قوانین سختگیرانهی IEEE 754) امکانپذیر نبود.
جایگزین رسمی برای crate معروف itoa
Rust 1.98 بالاخره سریالسازی عدد صحیح رو استاندارد کرده؛ با یه متد format_into و یه نوع جدید به اسم NumBuffer. طبق بنچمارکهای منتشرشده، عملکرد این پیادهسازی جدید همسطح crate قدیمی و پرکاربرد itoa است؛ یعنی خیلی از پروژههایی که تا الان برای تبدیل سریع عدد به رشته به این crate خارجی وابسته بودن، حالا میتونن مستقیم از کتابخونهی استاندارد استفاده کنن.
تضمین رسمی رفتار ManuallyDrop<Box<_>>
تو Rust 1.96، یه رفتار نامشخص (undefined behavior) مربوط به تعامل ManuallyDrop و Box رفع شده بود. تو این نسخه، مستندات رسمی آپدیت شده تا تضمین کنه این رفتار درست، برای همیشه پایدار میمونه؛ یعنی این دیگه یه رفع باگ ساده نیست، بلکه یه ضمانت رسمی و مستند از سمت زبونه (مرتبط با RFC 3336).
تغییرات زبانی
Lifetime shortening تو unsize coercion: حالا میشه lifetime یه &mut رو حتی تو موقعیت invariant، هنگام unsize-coercing کوتاه کرد. مثلاً میشه Cell<&'long mut i32> رو به Cell<&'short mut dyn Send> تبدیل کرد؛ این کوتاهسازی قبلاً فقط هنگام تبدیل &mut به &، یا & به & مجاز بود.
سختگیری بیشتر repr(transparent): این attribute حالا سختگیرتر شده دربارهی اینکه کدوم فیلدها layout «بیاهمیت» (trivial) دارن و میشه نادیدهشون گرفت؛ انواع repr(C)، انواع با فیلد خصوصی، و انواع #[non_exhaustive] دیگه trivial در نظر گرفته نمیشن.
لینتهای امنیتی جدید: یه لینت جدید deny-by-default به اسم invalid_runtime_symbol_definitions اضافه شده که فعلاً سمبلهای runtime اصلی مثل memcmp، memset، و strlen رو هدف میگیره (با برنامهریزی برای گسترش تو نسخههای بعدی). یه لینت warn-by-default هم به اسم c_void_returns اضافه شده که استفاده از core::ffi::c_void بهعنوان نوع بازگشتی رو چک میکنه.
API های جدید کتابخونهی استاندارد
چند تا API جدید هم پایدار شدن که ارزش دونستن دارن: str::substr_range و [T]::subslice_range (برای پیدا کردن محدودهی یه substring/subslice)، یه متد strip_circumfix برای هر دوی اینها، پیادهسازی Send و Sync برای std::process::CommandArgs، پارس کردن radix رو انواع NonZero، متدهای تبدیل lossy UTF-16 رو String، و چند تا کمککنندهی جدید برای mutation اتمیک. یه ماژول جدید به اسم std::range::legacy هم اضافه شده که برای نگهداری کدبیسهای قدیمیتر مفیده.
پلتفرمهای جدید
سه تا هدف جدید به لیست پلتفرمهای پشتیبانیشده اضافه شدن: ویژگیهای target d، e، و f تو RISC-V حالا تو cfg(target_feature = "?") پایدار شدن، و powerpc64-unknown-linux-gnuelfv2 و aarch64-unknown-linux-pauthtest هم بهعنوان هدف Tier 3 اضافه شدن.
نکتهی کوچیک ولی مهم برای نگهداری کد
یه نکتهی جالب اینه که ماکروی derive که تو {core,std}::derive در دسترسه، در واقع بهطور ناخواسته از نسخهی 1.96 پایدار شده بود، ولی حالا رسماً بهعنوان یه API پایدارشده پذیرفته شده. برای همین، حداقل نسخهی موردنیاز Rust (MSRV) برای این ماکرو، 1.96 است، نه 1.98؛ یه نکتهی ریز که موقع مستندسازی وابستگیهای پروژهت ارزش توجه داره.
چطور آپدیت کنیم
اگه از قبل Rust رو با rustup نصب کردی، آپدیت به این نسخه فقط یه دستوره:
rustup update stable
اگه تازهکاری، دستورالعمل نصب رو میتونی مستقیم از سایت رسمی Rust بگیری. برای دیدن کامل تغییرات کامپایلر، Cargo، و Clippy، بهتره یادداشتهای رسمی release رو رو گیتهاب چک کنی.
جمعبندی
Rust 1.98 نسخهاییه که تمرکز زیادی روی محاسبات عددی و performance گذاشته؛ متدهای algebraic برای اعشاریها و استانداردسازی سریالسازی عدد صحیح، هر دو مستقیم برای کدی که محاسبات سنگین یا حجم بالای تبدیل عدد به رشته داره مفیدن. تغییرات زبانی این نسخه هم بیشتر جنبهی سختگیری و ایمنسازی دارن (مثل repr(transparent) و لینتهای جدید) تا اضافه کردن قابلیتهای کاملاً جدید؛ یعنی برای اکثر پروژهها، آپگرید باید بدون درگیری خاصی پیش بره.
