[Перевод] Rust 1.59.0: встроенный ассемблер, деструктурирующее присваивание, отключение инкрементальной компиляции
Команда Rust публикует новую версию языка — 1.59.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Сегодняшний релиз выпал на день, когда внимание мира приковано к внезапному нападению сил Путина на Украину. До того, как погрузиться в детали нового релиза Rust, мы хотим заявить, что мы солидарны с народом Украины и выражаем нашу поддержку всем людям, затронутым этим конфликтом.
Если у вас есть предыдущая версия Rust, установленная через rustup
, то для обновления до версии 1.59.0 вам достаточно выполнить команду:
rustup update stable
Если у вас ещё нет rustup
, то можете установить его со страницы на нашем веб-сайте, а также ознакомиться с подробным описанием выпуска 1.59.0 на GitHub.
Что стабилизировано в 1.59.0
Встроенный ассемблер
Язык Rust теперь поддерживает встроенный ассемблер, что позволяет создавать приложения, которым требуется самый низкоуровневый контроль над их выполнением или доступ к специализированным машинным инструкциям.
Например, при компиляции под x86–64 вы теперь можете написать:
use std::arch::asm;
// Умножить x на 6 с помощью сдвигов и сложений
let mut x: u64 = 4;
unsafe {
asm!(
"mov {tmp}, {x}",
"shl {tmp}, 1",
"shl {x}, 2",
"add {x}, {tmp}",
x = inout(reg) x,
tmp = out(reg) _,
);
}
assert_eq!(x, 4 * 6);
Синтаксис форматирования строки, используемый для именования регистров в макросах asm!
и global_asm!
, используется в обычном форматировании строк Rust, поэтому он должен быть знакомым Rust-программистам.
Язык ассемблера и инструкции, доступные для встроенного ассемблера, различаются в зависимости от целевой архитектуры. Сегодня стабильный компилятор Rust поддерживает встроенную сборку на следующих архитектурах:
x86 и x86–64
ARM
AArch64
RISC-V
Вы можете увидеть больше примеров встроенного ассемблера в Rust By Example, а более подробную документацию найти в справочнике.
Деструктурирующее присваивание
Теперь вы можете использовать кортежи, срезы и структурные паттерны с левой стороны от присваивания.
let (a, b, c, d, e);
(a, b) = (1, 2);
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5, f: 3 };
assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
Это делает присваивания более согласованными с привязками let
, которые уже давно поддерживают это. Обратите внимание, что деструктурирующее присваивание не разрешено в таких операторах, как +=
.
Значения по умолчанию для константных обобщений и чередования
Для обобщённых типов теперь можно задать значения по умолчанию для их константных обобщений. Например, теперь вы можете написать следующее:
struct ArrayStorage {
arr: [T; N],
}
impl ArrayStorage {
fn new(a: T, b: T) -> ArrayStorage {
ArrayStorage {
arr: [a, b],
}
}
}
Ранее параметры типа требовалось писать до всех константных параметров. Это ограничение было ослаблено, и теперь вы можете чередовать их.
fn cartesian_product<
T, const N: usize,
U, const M: usize,
V, F
>(a: [T; N], b: [U; M]) -> [[V; N]; M]
where
F: FnMut(&T, &U) -> V
{
// ...
}
Предупреждения о будущей несовместимости
Иногда ошибки в компиляторе Rust заставляют его принимать код, который не должен был приниматься. Примером этого было заимствование полей упакованной структуры, разрешённое в безопасном коде.
Хотя это случается очень редко, такое поведение может быть весьма разрушительным — когда в крейте, используемом вашим проектом, есть код, который больше не будет разрешён. Вы этого можете даже не заметить, пока ваш проект необъяснимым образом не перестанет собираться!
Cargo теперь показывает вам предупреждения, когда зависимость будет отклонена будущей версией Rust. После запуска cargo build
или cargo check
вы сможете увидеть:
warning: the following packages contain code that will be rejected by a future version of Rust: old_dep v0.1.0
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
Вы можете запустить команду cargo report
, упомянутую в предупреждении, чтобы увидеть полный отчёт о коде, который будет отклонён. Это даёт вам время обновить вашу зависимость, прежде чем она сломает всю сборку.
Создание урезанных бинарных файлов
Часто вырезание информации, например отладочной, из поставляемых вами бинарных файлов, уменьшает их размер.
Это можно сделать вручную в любой момент после создания бинарного файла, но теперь cargo и rustc поддерживают урезание на этапе линковки. Для включения данной функциональности добавьте в Cargo.toml
следующее:
[profile.release]
strip = "debuginfo"
Это приведёт к вырезанию отладочной информации из релизных сборок. Вы также можете поставить "symbols"
или просто true
чтобы вырезать всю информацию о символах, которая возможна.
Стандартная библиотека обычно поставляется с отладочными символами и отладочной информацией, так что бинарные файлы Rust, собираемые без отладочной информации, по умолчанию включают в себя информацию об отладке стандартной библиотеки. Использование опции strip
позволяет вам удалить эту дополнительную информацию, чтобы создать более компактные бинарные файлы.
Для большей информации смотрите документацию Cargo.
Инкрементальная компиляция отключена по умолчанию
Версия 1.59.0 по умолчанию отключает инкрементный режим (если его явно не запросить через переменную среды RUSTC_FORCE_INCREMENTAL=1
). Это смягчает последствия известной ошибки #94124, которая может вызывать ошибки десериализации (и панику) во время компиляции с включённой инкрементной компиляцией.
Специальное исправление для #94124 появилось и в настоящее время находится в бета-версии 1.60, которая будет выпущена через шесть недель. В настоящее время мы не знаем о других проблемах, которые побудили бы принять решение об отключении инкрементной компиляции в стабильной версии 1.60, и если они не возникнут, вполне вероятно, что в стабильной версии 1.60 снова будет включена инкрементная компиляция. Инкрементная компиляция остаётся включённой по умолчанию в бета-версии и ночных каналах.
Как всегда, мы призываем пользователей тестировать ночные и бета-каналы и сообщать о найденных проблемах: особенно в отношении дополнительных ошибок. Это лучший способ быть уверенным, что команда Rust сможет оценить, есть ли поломка и какое количество пользователей она затрагивает.
Стабилизированные API
Стабилизированы следующие методы и реализации трейтов:
std::thread::available_parallelism
Result::copied
Result::cloned
arch::asm!
arch::global_asm!
ops::ControlFlow::is_break
ops::ControlFlow::is_continue
TryFrom
для u8 char::TryFromCharError
реализующиеClone
,Debug
,Display
,PartialEq
,Copy
,Eq
,Error
iter::zip
NonZeroU8::is_power_of_two
NonZeroU16::is_power_of_two
NonZeroU32::is_power_of_two
NonZeroU64::is_power_of_two
NonZeroU128::is_power_of_two
DoubleEndedIterator для ToLowercase
DoubleEndedIterator для ToUppercase
TryFrom<&mut [T]> for [T; N]
UnwindSafe для Once
RefUnwindSafe для Once
armv8 neon intrinsics для aarch64
Следующие ранее стабилизированные API стали const
:
mem::MaybeUninit::as_ptr
mem::MaybeUninit::assume_init
mem::MaybeUninit::assume_init_ref
ffi::CStr::from_bytes_with_nul_unchecked
Прочие изменения
В синтаксис, пакетный менеджер Cargo и анализатор Clippy также внесены некоторые изменения.
Участники 1.59.0
Множество людей объединились для создания Rust 1.59.0. Мы не смогли бы сделать это без всех вас. Спасибо!
От переводчиков
С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков. Также можете поддержать нас на OpenCollective.
Данную статью совместными усилиями перевели @belanchuk, @TelegaOvoshey и @funkill.