- PVSM.RU - https://www.pvsm.ru -

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

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

Введение

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

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

$ rustup update stable

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

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

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

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

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

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

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

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

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

Начиная с 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;

MaybeUninit место mem::uninitialized

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

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

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

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

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

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

NLL для Rust 2015

В объявлении о Rust 1.31.0 [14] мы рассказали вам о 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, поддерживаемым в обеих версиях, мы приближаемся к удалению старого проверятеля ссылок. Однако старый проверятель ссылок, к сожалению, принял беззвучный код [15], который он НЕ должен был принять.

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

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

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

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

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

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

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

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

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

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

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

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

Участники 1.36.0

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

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

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

Автор: Gymmasssorla

Источник [43]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/open-source/322908

Ссылки в тексте:

[1] публикации: https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html

[2] Rust: https://www.rust-lang.org/

[3] получить его: https://www.rust-lang.org/install.html

[4] Детальный обзор: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1360-2019-07-04

[5] Future: https://doc.rust-lang.org/std/future/trait.Future.html

[6] alloc: https://doc.rust-lang.org/alloc/index.html

[7] MaybeUninit<T>: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html

[8] NNL для Rust 2015: http://blog.pnkfx.org/blog/2019/06/26/breaking-news-non-lexical-lifetimes-arrives-for-everyone/

[9] --offline: https://doc.rust-lang.org/cargo/commands/cargo-build.html#cargo_build_manifest_options

[10] стабилизировал: https://github.com/rust-lang/rust/pull/59739

[11] mem::uninitialized: https://doc.rust-lang.org/std/mem/fn.uninitialized.html

[12] стабилизирован: https://github.com/rust-lang/rust/pull/60445

[13] статью Алексиса Бессесснера: https://gankro.github.io/blah/initialize-me-maybe/

[14] В объявлении о Rust 1.31.0: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#non-lexical-lifetimes

[15] беззвучный код: https://en.wikipedia.org/wiki/Soundness

[16] AST: https://en.wikipedia.org/wiki/Abstract_syntax_tree

[17] список пострадавших публичных крейтов: https://github.com/rust-lang/rust/issues/60680#issuecomment-495089654

[18] заменена: https://github.com/rust-lang/rust/pull/58623

[19] hashbrown: https://crates.io/crates/hashbrown

[20] SwissTable: https://abseil.io/blog/20180927-swisstables

[21] в среднем быстрее: https://perf.rust-lang.org/compare.html?start=b57fe74a27590289fd657614b8ad1f3eac8a7ad2&end=abade53a649583e40ed07c26ee10652703f09b58&stat=wall-time

[22] SipHash 1-3: https://en.wikipedia.org/wiki/SipHash

[23] cargo fetch: https://doc.rust-lang.org/cargo/commands/cargo-fetch.html

[24] статью Ника Камерона: https://www.ncameron.org/blog/cargo-offline/

[25] тут: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-136-2019-07-04

[26] dbg!: https://doc.rust-lang.org/std/macro.dbg.html

[27] Layout::from_size_align_unchecked: https://doc.rust-lang.org/core/alloc/struct.Layout.html#method.from_size_align_unchecked

[28] mem::needs_drop: https://doc.rust-lang.org/std/mem/fn.needs_drop.html

[29] NonNull::dangling: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.dangling

[30] NonNull::cast: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.cast

[31] task::Waker: https://doc.rust-lang.org/std/task/struct.Waker.html

[32] task::Poll: https://doc.rust-lang.org/std/task/enum.Poll.html

[33] VecDeque::rotate_left: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_left

[34] VecDeque::rotate_right: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_right

[35] Read::read_vectored: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_vectored

[36] Iterator::copied: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.copied

[37] BorrowMut<str> для String: https://github.com/rust-lang/rust/pull/60404

[38] str::as_mut_ptr: https://doc.rust-lang.org/std/primitive.str.html#method.as_mut_ptr

[39] Clippy: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-136

[40] спасибо: https://thanks.rust-lang.org/rust/1.36.0/

[41] русскоязычном Телеграм-чате: https://t.me/rustlang_ru

[42] чате для новичковых вопросов: https://t.me/rust_beginners_ru

[43] Источник: https://habr.com/ru/post/458848/?utm_campaign=458848&utm_source=habrahabr&utm_medium=rss