[Перевод] Rust 1.59.0: встроенный ассемблер, деструктурирующее присваивание, отключение инкрементальной компиляции

2df45555bd7492e1dab8b90ae125ac10

Команда 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.

© Habrahabr.ru