- PVSM.RU - https://www.pvsm.ru -
Команда Rust рада сообщить о новой версии языка — 1.66.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Если у вас есть предыдущая версия Rust, установленная через rustup, то для обновления до версии 1.66.0 вам достаточно выполнить команду:
rustup update stable
Если у вас ещё нет rustup, то можете установить его со страницы [1] на нашем веб-сайте, а также ознакомиться с подробным описанием выпуска 1.66.0 [2] на GitHub.
Если вы хотите помочь нам протестировать будущие выпуски, вы можете использовать beta (rustup default beta) или nightly (rustup default nightly) канал. Пожалуйста, сообщайте [3] обо всех встреченных вами ошибках.
Перечисления с числовым представлением теперь могут использовать явный дискриминант, даже если они имеют поля.
#[repr(u8)]
enum Foo {
A(u8),
B(i8),
C(bool) = 42,
}
Ранее вы могли использовать явные дискриминанты в перечислениях, но только если ни один из вариантов не содержал поля. Явные дискриминанты полезны при передаче значения между разными языками и если значение перечисления нужно определить в обоих языках. Например:
#[repr(u8)]
enum Bar {
A,
B,
C = 42,
D,
}
Здесь перечисление Bar гарантированно будет иметь то же представление в памяти, что и u8. Кроме того, у варианта Bar::C гарантированно есть дискриминант 42. Варианты без явно указанных значений будут иметь дискриминанты, которые автоматически назначаются в соответствии с их порядком в исходном коде, поэтому у Bar::A будет дискриминант 0, у Bar::B будет 1, а у Bar::D будет 43. Без этой функции единственным способом установить явное значение Bar::C было бы добавить 41 ненужный вариант перед ним!
Примечание: в то время как для перечислений без полей можно проверить дискриминант через приведение as (например, Bar::C as u8), Rust не предоставляет способа на уровне языка для доступа к необработанному дискриминанту перечисления с полями. Вместо этого для проверки дискриминанта перечисления с полями необходимо использовать небезопасный в настоящее время код. Поскольку эта функция предназначена для использования с межъязыковым FFI, где уже необходим небезопасный код, мы надеемся, что это не станет слишком большой дополнительной нагрузкой. Пока же если всё, что вам нужно, — это непрозрачный дескриптор дискриминанта, см. функцию std::mem::discriminant.
core::hint::black_boxКогда исследуется или оценивается машинный код, сгенерированный компилятором, бывает полезно отключить оптимизацию для определённых мест. В следующем примере функция push_cap 4 раза вызывает в цикле Vec::push:
fn push_cap(v: &mut Vec<i32>) {
for i in 0..4 {
v.push(i);
}
}
pub fn bench_push() -> Duration {
let mut v = Vec::with_capacity(4);
let now = Instant::now();
push_cap(&mut v);
now.elapsed()
}
Если вы посмотрите оптимизированный вывод компилятора для x86_64, то заметите, что он выглядит достаточно коротко:
example::bench_push:
sub rsp, 24
call qword ptr [rip + std::time::Instant::now@GOTPCREL]
lea rdi, [rsp + 8]
mov qword ptr [rsp + 8], rax
mov dword ptr [rsp + 16], edx
call qword ptr [rip + std::time::Instant::elapsed@GOTPCREL]
add rsp, 24
ret
Фактически вся функция push_cap, которую мы хотели оценить, была оптимизирована!
Мы можем обойти это при помощи новой стабилизированной функции black_box. Функционально black_box не очень интересна: она лишь берёт значение, которое вы ей передали, и возвращает его обратно. Однако внутри компилятор обрабатывает black_box как функцию, которая что-то делает с передаваемым ей вводом и возвращает какое-то значение (как и следует из её названия).
Это очень полезно для отключение оптимизаций — как той, что мы видели выше. Например, мы можем подсказать компилятору, что вектор будет использоваться для чего-то после каждой итерации цикла.
use std::hint::black_box;
fn push_cap(v: &mut Vec<i32>) {
for i in 0..4 {
v.push(i);
black_box(v.as_ptr());
}
}
Теперь мы можем найти развёрнутый цикл for в нашем оптимизированном ассемблерном выводе [4]:
mov dword ptr [rbx], 0
mov qword ptr [rsp + 8], rbx
mov dword ptr [rbx + 4], 1
mov qword ptr [rsp + 8], rbx
mov dword ptr [rbx + 8], 2
mov qword ptr [rsp + 8], rbx
mov dword ptr [rbx + 12], 3
mov qword ptr [rsp + 8], rbx
Вы также можете увидеть побочный эффект вызова black_box в этом ассемблерном выводе. Инструкция mov qword ptr [rsp + 8], rbx бесполезно повторяется после каждой итерации. Эта инструкция записывает адрес v.as_ptr() в качестве первого аргумента функции, которая фактически никогда не вызывается.
Обратите внимание, что сгенерированный код вообще не связан с возможностью распределения памяти, введённого вызовом push. Это потому, что компилятор всё ещё опирается на тот факт, что мы вызвали Vec::with_capacity(4) в функции bench_push. Вы можете поиграть с размещением black_box или попробовать использовать его в нескольких местах, чтобы увидеть его влияние на оптимизацию компилятора.
Rust 1.62.0 представил cargo add — утилиту командной строки для добавления зависимостей в ваш проект. В этой же версии вы сможете использовать cargo remove для их удаления.
proc_macro::Span::source_text [5]u*::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed} [6]i*::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned} [7]i*::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned} [8]BTreeSet::{first, last, pop_first, pop_last} [9]BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last} [10]Добавлена реализация AsFd для типов блокировок стандартных потоков для WASI [11]impl TryFrom<Vec<T>> for Box<[T; N]> [12]core::hint::black_box [13]Duration::try_from_secs_{f32,f64} [14]Option::unzip [15]std::os::fd [16]Выпуск Rust 1.66 включает и другие изменения:
..=X.Проверьте всё, что изменилось в Rust [2], Cargo [17] и Clippy [18].
Многие люди собрались вместе, чтобы создать Rust 1.66.0. Без вас мы бы не справились. Спасибо! [19]
С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате [20] или же в аналогичном чате для новичковых вопросов [21]. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков [22].
Данную статью совместными усилиями перевели andreevlex [23], TelegaOvoshey [24] и funkill [25].
Автор:
RustLangRu
Источник [26]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/381405
Ссылки в тексте:
[1] страницы: https://www.rust-lang.org/install.html
[2] подробным описанием выпуска 1.66.0: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1660-2022-12-15
[3] сообщайте: https://github.com/rust-lang/rust/issues/new/choose
[4] оптимизированном ассемблерном выводе: https://rust.godbolt.org/z/Ws1GGbY6Y
[5] proc_macro::Span::source_text: https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text
[6] u*::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed
[7] i*::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned
[8] i*::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned
[9] BTreeSet::{first, last, pop_first, pop_last}: https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first
[10] BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}: https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value
[11] Добавлена реализация AsFd для типов блокировок стандартных потоков для WASI: https://github.com/rust-lang/rust/pull/101768/
[12] impl TryFrom<Vec<T>> for Box<[T; N]>: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E
[13] core::hint::black_box: https://doc.rust-lang.org/stable/std/hint/fn.black_box.html
[14] Duration::try_from_secs_{f32,f64}: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32
[15] Option::unzip: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip
[16] std::os::fd: https://doc.rust-lang.org/stable/std/os/fd/index.html
[17] Cargo: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15
[18] Clippy: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-166
[19] Спасибо!: https://thanks.rust-lang.org/rust/1.66.0/
[20] русскоязычном Телеграм-чате: https://t.me/rustlang_ru
[21] чате для новичковых вопросов: https://t.me/rust_beginners_ru
[22] чат переводчиков: https://t.me/rustlang_ru_translations
[23] andreevlex: https://habr.com/ru/users/andreevlex/
[24] TelegaOvoshey: https://habr.com/ru/users/telegaovoshey/
[25] funkill: https://habr.com/ru/users/funkill/
[26] Источник: https://habr.com/ru/post/706176/?utm_source=habrahabr&utm_medium=rss&utm_campaign=706176
Нажмите здесь для печати.