- PVSM.RU - https://www.pvsm.ru -
Команда Rust рада сообщить о выпуске новой версии, 1.40.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Если вы установили предыдущую версию Rust средствами rustup
, то для обновления до версии 1.40.0 вам достаточно выполнить следующую команду:
$ rustup update stable
Если у вас ещё не установлен rustup
, вы можете установить его [1] с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску [2] на GitHub.
Основными новшествами являются введение атрибута #[non_exhaustive]
, улучшения macros!()
и #[attribute]
. Наконец, миграционные предупреждения анализатора заимствований стали ошибками в Rust 2015. Смотрите подробности выпуска [2] для дополнительной информации.
#[non_exhaustive]
структуры, перечисления и варианты перечисленийПредположим, вы являетесь автором библиотеки alpha
, которая содержит pub struct Foo
. Вы хотели бы сделать поля структуры alpha::Foo
публичными, но не уверены, придётся ли вам в будущих выпусках добавить больше полей в Foo
. Возникает дилемма: либо вы делаете поля приватными с последующими неудобствами, либо вы рискуете поставить пользователей в зависимость от полей и потом нарушит их код при добавлении новых. В Rust 1.40.0 представлен способ решить проблему с помощью #[non_exhaustive]
.
Атрибут #[non_exhaustive]
прикрепляется к структуре или варианту перечисления и препятствует полному сопоставлению полей, созданию упомянутой структуры или варианта вне крейта с их объявлением. Следующий пример демонстрирует ошибки в крейте beta
, зависящего от alpha
:
// alpha/lib.rs:
#[non_exhaustive]
struct Foo {
pub a: bool,
}
enum Bar {
#[non_exhaustive]
Variant { b: u8 }
}
fn make_foo() -> Foo { ... }
fn make_bar() -> Bar { ... }
// beta/lib.rs:
let x = Foo { a: true }; //~ ОШИБКА
let Foo { a } = make_foo(); //~ ОШИБКА
let Foo { a, .. } = make_foo(); //~ OK
// -- `beta` все еще будет компилироваться при добавлении полей.
let x = Bar::Variant { a: 42 }; //~ ОШИБКА
let Bar::Variant { b } = make_bar(); //~ ОШИБКА
let Bar::Variant { b, .. } = make_bar(); //~ OK
// -- `beta` все еще будет компилироваться...
Что же происходит за кулисами? Видимость конструкторов для #[non_exhaustive]
структуры или варианта перечисления будет понижена до pub(crate)
, тем самым запрещая их использование в сторонних крейтах.
Возможно, что более важным аспектом #[non_exhaustive]
является то, что атрибут может быть прикреплён к самим перечислениям. Вот код, взятый из std::cmp::Ordering
[3]:
#[non_exhaustive]
pub enum Ordering { Relaxed, Release, Acquire, AcqRel, SeqCst }
В данном случае #[non_exhaustive]
гарантирует возможность добавления новых вариантов в будущем. Это достигается запретом другим пакетам к использованию исчерпывающего сопоставления с образом для Ordering
. Компилятор бы отклонил следующее:
match ordering {
Relaxed | Release | Acquire | AcqRel | SeqCst => { /* logic */ }
//~^ ОШИБКА; если новый вариант был бы добавлен,
// это сломалось бы, если ошибки не было бы с самого начала.
}
Вместо этого другие пакеты теперь должны учитывать возможность появления новых вариантов перечисления, например добавляя подстановочный знак _
:
match ordering {
Relaxed | Release | Acquire | AcqRel | SeqCst => { /* logic */ }
_ => { /* logic */ } // OK; если будут добавлены новые варианты, ничего не сломается.
}
Подробная информация об атрибуте #[non_exhaustive]
доступна в отчёте о стабилизации [4].
В 1.40.0 мы внесли несколько улучшений в макросы и атрибуты, включая:
Вызов процедурных макросов mac!()
в контекстах типов. [5]
Например, можно написать type Foo = expand_to_type!(bar);
где expand_to_type
будет процедурным макросом.
Макросы в extern { ... }
блоках. [5]
Этот блок включает макросы make_item!()
. Например:
macro_rules! make_item { ($name:ident) => { fn $name(); } }
extern {
make_item!(alpha);
make_item!(beta);
}
Атрибутные процедурные макросы для элементов в extern { ... }
блоках [6] теперь также поддерживаются:
extern "C" {
#[my_identity_macro] //~ Давайте предположим, что это расширяется до `fn foo();`.
fn foo();
}
Генерация macro_rules!
элементов в процедурных макросах. [7]
Макросы с синтаксисом функций (mac!()
) и атрибуты (#[mac]
) теперь могут генерировать элементы macro_rules!
. Подробнее смотрите в прилагаемом отчёте о стабилизации.
Теперь сопоставление с помощью $m:meta
[8] поддерживает произвольные значения TokenStream
[9].
То есть следующий код является корректным:
macro_rules! accept_meta { ($m:meta) => {} }
accept_meta!( my::path );
accept_meta!( my::path = "lit" );
accept_meta!( my::path ( a b c ) );
accept_meta!( my::path [ a b c ] );
accept_meta!( my::path { a b c } );
В выпуске 1.35.0 мы сообщили [10], что NLL
появился в редакции Rust 2015 после первого выпуска для 2018 редакции в Rust 1.31 [11].
Как мы сказали, старый анализатор заимствований мог допустить небезопасное управление памятью, и с помощью нового анализатора (NLL borrow checker) эти недочёты были решены. Так как эти ошибки могли нарушить работу стабильного кода, мы решили постепенно вводить эти ошибки, проверяя разрешит ли сборку программы старый анализатор, и запретит ли её новый. В этих случаях ошибки заменялись предупреждениями.
Предыдущий выпуск Rust 1.39.0 заменил эти предупреждения на ошибки для кода с 2018 редакцией [12]. Rust 1.40.0 применит те же самые изменения для кода 2015 редакции [13], навсегда закрывая эти дыры в безопасности. Вместе с этим компилятор даже почистили от старого кода [14]!
Если ваш проект не собирается из-за вышеописанных изменений, или вы хотите узнать больше, читайте пост Niko Matsakis's [15].
Начиная с Rust 1.40.0, следующая функция помечена как константная (const fn
):
is_power_of_two
[16] для беззнаковых целых чисел [17]В Rust 1.40.0 были стабилизированы следующие функции и макросы:
todo!()
[18]
Более короткая, запоминающаяся и удобная версия макроса unimplemented!()
[19].
slice::repeat
[20]
Создаёт Vec<T>
из n
повторений среза.
mem::take
[21]
Эта функция забирает значения из изменяемой ссылки и заменяет их значением по умолчанию для данного типа. Она похожа на Option::take
[22] и Cell::take
[23] и является удобным сокращением для mem::replace(&mut dst, Default::default())
[24].
BTreeMap::get_key_value
[25] и HashMap::get_key_value
[26]
Возвращает пару ключ-значение, соответствующие предоставленному ключу.
Option::as_deref
[27], Option::as_deref_mut
[28]
Они работают подобно Option::as_ref
[29] и Option::as_mut
[30], но используют Deref
[31] и DerefMut
[32] соответственно, таким образом, opt_box.as_deref()
и opt_box.as_deref_mut()
, где opt_box: Option<Box<T>>
, создают Option<&T>
и Option<&mut T>
соответственно.
Option::flatten
[33]
Эта функция, подобно Iterator::flatten
[34], разворачивает Option<Option<T>>
в Option<T>
, производя Some(x)
для Some(Some(x))
и None
в противном случае.
UdpSocket::peer_addr
[35]
Возвращает адрес удалённого узла, к которому подключён сокет.
{f32,f64}::to_be_bytes
[36], {f32,f64}::to_le_bytes
[37], {f32,f64}::to_ne_bytes
[38], {f32,f64}::from_be_bytes
[39], {f32,f64}::from_le_bytes
[40] и {f32,f64}::from_ne_bytes
[41]
Возвращают представление в памяти числа с плавающей точкой в виде массива байт с big-endian (network), little-endian или native-endian порядком байт.
Синтаксис [2], пакетный менеджер Cargo [42] и анализатор Clippy [43] также претерпели некоторые изменения.
Пожалуйста, прочтите заметки о совместимости [44], чтобы узнать, затронут ли вас эти изменения.
Множество людей собрались вместе, чтобы создать Rust 1.40.0. Мы не смогли бы сделать это без всех вас, спасибо [45]!
С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате [46] или же в аналогичном чате для новичковых вопросов [47].
Данную статью совместными усилиями перевели andreevlex [48], blandger [49], funkill [50], Hippolot [51], P0lunin [52], PsyHaSTe [53] и LooMaclin [54].
Автор: RustLangRu
Источник [55]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/340682
Ссылки в тексте:
[1] установить его: https://www.rust-lang.org/install.html
[2] подробные примечания к выпуску: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1400-2019-12-19
[3] std::cmp::Ordering
: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html
[4] отчёте о стабилизации: https://github.com/rust-lang/rust/issues/44109#issuecomment-533356866
[5] Вызов процедурных макросов mac!()
в контекстах типов.: https://github.com/rust-lang/rust/pull/63931/#issuecomment-526362396
[6] extern { ... }
блоках: https://doc.rust-lang.org/nightly/reference/items/external-blocks.html
[7] Генерация macro_rules!
элементов в процедурных макросах.: https://github.com/rust-lang/rust/pull/64035#issuecomment-533890826
[8] Теперь сопоставление с помощью $m:meta
: https://github.com/rust-lang/rust/pull/63674
[9] произвольные значения TokenStream
: https://github.com/rust-lang/rust/pull/57367#issuecomment-457882109
[10] мы сообщили: https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#nll-for-rust-2015
[11] Rust 1.31: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#non-lexical-lifetimes
[12] 2018 редакцией: https://github.com/rust-lang/rust/pull/63565
[13] 2015 редакции: https://github.com/rust-lang/rust/pull/64221
[14] компилятор даже почистили от старого кода: https://github.com/rust-lang/rust/pull/64790
[15] пост Niko Matsakis's: https://blog.rust-lang.org/2019/11/01/nll-hard-errors.html
[16] is_power_of_two
: https://doc.rust-lang.org/std/primitive.u8.html#method.is_power_of_two
[17] беззнаковых целых чисел: https://github.com/rust-lang/rust/pull/65092
[18] todo!()
: https://doc.rust-lang.org/std/macro.todo.html
[19] unimplemented!()
: https://doc.rust-lang.org/std/macro.unimplemented.html
[20] slice::repeat
: https://doc.rust-lang.org/std/primitive.slice.html#method.repeat
[21] mem::take
: https://doc.rust-lang.org/std/mem/fn.take.html
[22] Option::take
: https://doc.rust-lang.org/std/option/enum.Option.html#method.take
[23] Cell::take
: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.take
[24] mem::replace(&mut dst, Default::default())
: https://doc.rust-lang.org/std/mem/fn.replace.html
[25] BTreeMap::get_key_value
: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.get_key_value
[26] HashMap::get_key_value
: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_key_value
[27] Option::as_deref
: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_deref
[28] Option::as_deref_mut
: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_deref_mut
[29] Option::as_ref
: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref
[30] Option::as_mut
: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_mut
[31] Deref
: https://doc.rust-lang.org/std/ops/trait.Deref.html
[32] DerefMut
: https://doc.rust-lang.org/std/ops/trait.DerefMut.html
[33] Option::flatten
: https://doc.rust-lang.org/std/option/enum.Option.html#method.flatten
[34] Iterator::flatten
: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.flatten
[35] UdpSocket::peer_addr
: https://doc.rust-lang.org/std/net/struct.UdpSocket.html#method.peer_addr
[36] {f32,f64}::to_be_bytes
: https://doc.rust-lang.org/std/primitive.f32.html#method.to_be_bytes
[37] {f32,f64}::to_le_bytes
: https://doc.rust-lang.org/std/primitive.f32.html#method.to_le_bytes
[38] {f32,f64}::to_ne_bytes
: https://doc.rust-lang.org/std/primitive.f32.html#method.to_ne_bytes
[39] {f32,f64}::from_be_bytes
: https://doc.rust-lang.org/std/primitive.f32.html#method.from_be_bytes
[40] {f32,f64}::from_le_bytes
: https://doc.rust-lang.org/std/primitive.f32.html#method.from_le_bytes
[41] {f32,f64}::from_ne_bytes
: https://doc.rust-lang.org/std/primitive.f32.html#method.from_ne_bytes
[42] пакетный менеджер Cargo: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-140-2019-12-19
[43] анализатор Clippy: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-140
[44] заметки о совместимости: https://github.com/rust-lang/rust/blob/master/RELEASES.md#compatibility-notes
[45] спасибо: https://thanks.rust-lang.org/rust/1.40.0/
[46] русскоязычном Телеграм-чате: https://t.me/rustlang_ru
[47] чате для новичковых вопросов: https://t.me/rust_beginners_ru
[48] andreevlex: https://habr.com/ru/users/andreevlex/
[49] blandger: https://habr.com/ru/users/blandger/
[50] funkill: https://habr.com/ru/users/funkill/
[51] Hippolot: https://habr.com/ru/users/hippolot/
[52] P0lunin: https://habr.com/ru/users/p0lunin/
[53] PsyHaSTe: https://habr.com/ru/users/psyhaste/
[54] LooMaclin: https://habr.com/ru/users/loomaclin/
[55] Источник: https://habr.com/ru/post/481070/?utm_campaign=481070&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.