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

b5d5cd733475576383afb7828e1d166a

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

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

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

$ rustup update stable

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

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

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

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

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

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

Начиная с Rust 1.36.0, части крейта std, зависимые от глобального аллокатора, например, Vec, сейчас доступны в крейте 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;

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

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

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

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

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

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

В объявлении о 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, истории о правке «беззвучных дыр», и о том, что вы можете сделать с предупреждениями компилятора, прочтите статью Феликса Клока.

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

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

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

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

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


  • Макрос dbg! стал поддерживать множественные аргументы;


  • Некоторые методы были помечены словом const:


  • Стабилизированы некоторые API, включая:


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

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

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


© Habrahabr.ru