Open source
System Programming
Rust

Выпуск Rust 1.36.0: Трейт Future, стабилизация alloc и MaybeUninit<T>

Представляю вашему вниманию перевод публикации о новой версии всеми любимого языка программирования Rust.


Введение


Команда по разработке языка программирования Rust рада анонсировать новую версию, 1.36.0. Rust — это язык программирования, позволяющий каждому разрабатывать надёжное и быстрое ПО.


Если предыдущую версию Rust вы установили средствами rustup, получение текущей версии не составит особого труда:


$ rustup update stable

Если у вас всё ещё нет rustup, вы можете получить его с соответствующей страницы на нашем сайте. Детальный обзор данного релиза доступен на GitHub.


Что вошло в стабильную версию?


Данный релиз привнёс множество изменений, включая стабилизацию долгожданного трейта Future, крейта alloc, структуры MaybeUninit<T>, NLL для Rust 2015, новую реализацию HashMap<K, V> и поддержку флага --offline в Cargo.


Ниже описаны наиболее значительные изменения, однако вы также можете посмотреть детальный список нововведений для дополнительной осведомлённости.


Стабилизация трейта Future


Rust 1.36.0 стабилизировал долгожданный трейт Future!


Мы надеемся, что это нововведение позволит популярным крейтам, библиотекам и в целом всей экосистеме подготовиться к синтаксису async/.await, стабилизация которого планируется на недалёкое будущее.


Стабилизация крейта alloc


До версии 1.36.0 стандартная библиотека состояла из крейтов std, core и proc_macro. Крейт core имел базовую функциональность (такую как Iterator и Copy) и мог быть использован в средах с #![no_std], так как он не налагал никаких требований. Между тем, крейт std поставлял такие типы, как Box<T>, а также функциональность операционной системы (глобальный аллокатор).


Начиная с Rust 1.36.0, компоненты крейта std, зависимые от глобального аллокатора, например, Vec<T>, сейчас доступны в крейте alloc. Крейт std, тем временем, реэкспортирует данные компоненты.


В то время как программы с #![no_std], использующие крейт alloc, всё ещё требуют канала nightly, библиотеки с #![no_std] могут использовать крейт alloc в стабильном Rust.


Также отметим, что все "обычные" программы (без #![no_std]) в своих зависимостях способны содержать описанные выше библиотеки с #![no_std]. Мы надеемся, что это будет содействовать разработке экосистемы, совместимой с #![no_std].


Если вы являетесь разработчиком библиотеки, требующей примитивы аллокации для функционирования, советуем пометить свою библиотеку как совместимой с #![no_std], используя следующий синтаксис в начале файла lib.rs:


#![no_std]

extern crate alloc;

use alloc::vec::Vec;

MaybeUninit место mem::uninitialized


В предыдущих релизах Rust функция mem::uninitialized разрешала вам отменять проверки инициализации, так как полагала, что вы УЖЕ выполнили инициализацию типа T, не делая ничего. Одно из использований данной функции была "ленивая" аллокация массивов.


Однако mem::uninitalized является чрезмерно опасной операцией, которая не может быть правильно использована с компилятором Rust, предполагающим, что все значения проинициализированы должным образом.


Например, вызов mem::uninitialized::<bool>() немедленно вызовет неопределённое поведение, так как с точки зрения Rust, неинициализированные биты являются либо нулём (false), либо единицей (true), и лишь два вышеописанных паттерна подходят для типа bool.


Чтобы разрешить данную ситуацию, в Rust 1.36.0 был стабилизирован тип MaybeUninit<T>. Компилятор Rust теперь не предполагает, что MaybeUninit<T> является инициализированным типом T. Тем самым, вы можете выполнять постепенную инициализацию более безопасно и наконец-то использовать .assume_init() когда вы уверены, что maybe_t: MaybeUninit<T> содержит инициализированный тип T.


Так как MaybeUninit<T> является более безопасной альтернативой, начиная с Rust 1.38, функция mem::uninitialized будет помечена устаревшей.


Чтобы узнать больше о неинициализированной памяти, mem::uninitialized и MaybeUninit<T>, почитайте статью Алексиса Бессесснера. Стандартная библиотека также содержит достаточную документацию о MaybeUninit<T>.


NLL для Rust 2015


В объявлении о Rust 1.31.0 мы рассказали вам о NLL (нелексические лайфтаймы), нововведении в язык, делающим контроллера ссылок (borrow checker) умнее и дружелюбнее. Например, теперь вы можете написать так:


fn main() {
    let mut x = 5;
    let y = &x;
    let z = &mut x; // Не было разрешено до 1.31.0
}

В 1.31.0 NLL был стабилизирован только для Rust 2018, и предполагалось, что мы перенесём его в Rust 2015 в будущем. Это было сделано в Rust 1.36.0, NLL стал доступным для Rust 2015.


С NLL, поддерживаемым в обеих версиях, мы приближаемся к удалению старого контроллера ссылок. Однако старый контроллер ссылок, к сожалению, принял некорректный код, который он НЕ должен был принять.


И, как результат, NLL сейчас находится на стадии "миграции", в которой мы будем выдавать предупреждения вместо ошибок в том случае, если контроллер ссылок NLL не одобрит код, который бы одобрил старый контроллер ссылок на основе AST. Советуем взглянуть на список пострадавших публичных крейтов.


Чтобы узнать больше о NLL, MIR, об исправлении соответствующих проблем целостности, а также о том, что можно сделать с появившимися предупреждениями компилятора, прочтите статью Феликса Клока.


Новая реализация HashMap


В Rust 1.36.0 предыдущая реализация HashMap<K, V> была заменена реализацией из крейта hashbrown, основанной на дизайне SwissTable. Интерфейс остался прежним, но нынешняя реализация в среднем быстрее и потребляет меньше памяти. Однако заметьте, что стандартная реализация всё ещё использует алгоритм SipHash 1-3.


Поддержка --offline в Cargo


Во время большинства сборок Cargo не использует вашу сеть. Однако в некоторых моментах, например, когда новая зависимость была добавлена, Cargo всё же будет пытаться получить доступ к сети. Иногда такое поведение недопустимо (в изолированной системе или в самолёте).


Rust 1.36.0 стабилизировал новый флаг --offline. Данный флаг отменяет алгоритм разрешения зависимостей, вместо этого используя локальные закешированные зависимости.


Если запрашиваемые крейты недоступны без сети, которая была отключена, то Cargo завершит работу с ошибкой. Чтобы предварительно заполнить локальный кеш до ухода из сети, используйте команду cargo fetch, загружающую все необходимые зависимости для конкретного проекта.


Чтобы узнать больше о --offline и cargo fetch, прочтите статью Ника Камерона. Другие изменения в Cargo детально описаны тут.


Изменения в библиотеке



Другие изменения


Подробные описания изменений в версии 1.36.0 доступны для Rust, стандартной библиотеки, Cargo и Clippy.


Участники 1.36.0


Множество людей собрались вместе, чтобы создать Rust 1.36.0. Мы не смогли бы сделать это без всех вас, спасибо!


От переводчика


С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов.



+57
6.1k 20
Support the author
Comments 27
Top of the day