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

Если у вас есть предыдущая версия Rust, установленная через rustup, то для обновления до версии 1.89.0 вам достаточно выполнить команду:

$ rustup update stable

Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску на GitHub.

Если вы хотите помочь нам протестировать будущие выпуски, вы можете использовать канал beta (rustup default beta) или nightly (rustup default nightly). Пожалуйста, сообщайте обо всех встреченных вами ошибках.

Что стабилизировано в 1.89.0

Явный вывод аргументов для константных обобщений

Теперь Rust поддерживает использование _ в качестве аргумента для константных обобщённых параметров, что позволяет выводить значение из окружающего контекста:

pub fn all_false<const LEN: usize>() -> [bool; LEN] {
  [false; _]
}

Аналогично правилам, когда _ разрешается в качестве типа, _ не разрешается в качестве аргумента для константных обобщений в сигнатуре:

// Так делать нельзя
pub const fn all_false<const LEN: usize>() -> [bool; _] {
  [false; LEN]
}

// И так тоже
pub const ALL_FALSE: [bool; _] = all_false::<10>();

Проверка для несовпадающего синтаксиса времён жизни

Сокращение времён жизни в сигнатурах функций — это удобная особенность языка Rust, но она может стать камнем преткновения как для новичков, так и для опытных разработчиков. Это особенно заметно, когда времена жизни выводятся в типах, где синтаксически неочевидно их наличие:

// Возвращаемый тип `std::slice::Iter` имеет время жизни,
// но визуально это никак не показано.
//
// Сокращение времени жизни выводит, что время жизни
// возвращаемого типа такое же, как у `scores`.
fn items(scores: &[u8]) -> std::slice::Iter<u8> {
   scores.iter()
}

Подобный код теперь будет по умолчанию выдавать предупреждение:

warning: hiding a lifetime that's elided elsewhere is confusing
 --> src/lib.rs:1:18
  |
1 | fn items(scores: &[u8]) -> std::slice::Iter<u8> {
  |                  ^^^^^     -------------------- the same lifetime is hidden here
  |                  |
  |                  the lifetime is elided here
  |
  = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
  = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
help: use `'_` for type paths
  |
1 | fn items(scores: &[u8]) -> std::slice::Iter<'_, u8> {
  |                                             +++

Впервые мы попытались улучшить эту ситуацию ещё в 2018 году в рамках группы проверок rust_2018_idioms, но сильный отклик на проверку elided_lifetimes_in_paths показал, что она была слишком "грубым инструментом", так как выдавала предупреждения о временах жизни, которые не важны для понимания функции:

use std::fmt;

struct Greeting;

impl fmt::Display for Greeting {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //                -----^^^^^^^^^ ожидаемый параметр времени жизни
        // Знание о том, что `Formatter` имеет время жизни, не помогает программисту
        "howdy".fmt(f)
    }
}

Затем мы поняли, что путаница, которую мы хотим устранить, возникает, когда:

  1. Правила вывода сокращения времён жизни связывают входное время жизни с выходным;

  2. Синтаксически неочевидно, что время жизни существует.

В Rust есть два синтаксических элемента, которые указывают на существование времени жизни: & и '. Символ ' подразделяется на выводимое время жизни '_ и именованные времена жизни 'a. Когда тип использует именованное время жизни, сокращение не будет выводить время жизни для этого типа. Используя эти критерии, мы можем выделить три группы:

Очевидно, что есть время жизни

Разрешено сокращение времени жизни

Примеры

Нет

Да

ContainsLifetime

Да

Да

&T, &'_ T, ContainsLifetime<'_>

Да

Нет

&'a T, ContainsLifetime<'a>

Проверка mismatched_lifetime_syntaxes проверяет, принадлежат ли входные и выходные данные функции к одной и той же группе. Для примера выше &[u8] относится ко второй группе, а std::slice::Iter<u8> — к первой. Мы говорим, что времена жизни в первой группе являются скрытыми.

Поскольку времена жизни на входе и выходе принадлежат к разным группам, проверка выдаст предупреждение для этой функции, уменьшая путаницу относительно того, когда значение имеет значимое время жизни, которое не очевидно визуально.

Проверка mismatched_lifetime_syntaxes заменяет проверку elided_named_lifetimes, которая делала нечто похожее специально для именованных времён жизни.

Дальнейшая работа над проверкой elided_lifetimes_in_paths предполагает её разделение на более сфокусированные подпроверки с целью в конечном итоге начать выдавать предупреждения для их подмножества.

Больше возможностей для целевых платформ x86

Атрибут target_feature теперь поддерживает функции sha512, sm3, sm4, kl и widekl для x86. Кроме того, на x86 также поддерживается ряд встроенных функций и возможностей avx512:

#[target_feature(enable = "avx512bw")]
pub fn cool_simd_code(/* .. */) -> /* ... */ {
    /* ... */
}

Кросс-компилируемые документационные тесты

Теперь документационные тесты будут запускаться при выполнении команды cargo test --doc --target other_target. Это может привести к поломкам, поскольку тесты, которые ранее не запускались и могли завершиться с ошибкой, теперь будут использованы.

Падающие тесты можно отключить, добавив к документационному тесту аннотацию ignore-<target> (документация).

/// ```ignore-x86_64
/// panic!("something")
/// ```
pub fn my_function() { }

i128 и u128 в функциях extern "C"

Типы i128 и u128 теперь можно использовать в функциях extern "C" без предупреждения, поскольку они больше не вызывают проверку improper_ctypes_definitions. Однако есть несколько нюансов:

  • Типы Rust ABI- и layout- совместимы с (беззнаковым) __int128 в C, если этот тип доступен.

  • На платформах, где __int128 недоступен, i128 и u128 не обязательно совпадают с каким-либо типом C.

  • i128 не обязательно совместим с _BitInt(128) на любой платформе, поскольку _BitInt(128) и __int128 могут иметь разный ABI (как, например, на x86-64).

Это последнее обновление, связанное с прошлогодними изменениями в layout.

Понижение x86_64-apple-darwin до Tier 2 с инструментами хоста

GitHub скоро прекратит предоставлять бесплатные раннеры macOS x86_64 для публичных репозиториев. Apple также анонсировала свои планы по прекращению поддержки архитектуры x86_64.

В соответствии с этими изменениями, проект Rust находится в процессе понижения таргета x86_64-apple-darwin с Tier 1 с инструментами хоста до Tier 2 с инструментами хоста. Это означает, что для этого таргета, включая такие инструменты, как rustc и cargo, будет гарантирована сборка, но не гарантируется прохождение нашего автоматизированного набора тестов.

Мы ожидаем, что RFC о понижении до Tier 2 с инструментами хоста будет принят между релизами Rust 1.89 и 1.90. Это означает, что Rust 1.89 будет последним релизом, где x86_64-apple-darwin является таргетом Tier 1.

Для пользователей это изменение не окажет немедленного влияния. Сборки как стандартной библиотеки, так и компилятора по-прежнему будут распространяться проектом Rust для использования через rustup или альтернативные методы установки, пока таргет остаётся в Tier 2. Но вероятно, что со временем уменьшение тестового покрытия для этого таргета приведёт к поломкам или потере совместимости без дополнительных объявлений.

C ABI, соответствующий стандартам, для таргета wasm32-unknown-unknown

Функции extern "C" для таргета wasm32-unknown-unknown теперь имеют ABI, соответствующий стандартам. Подробнее об этом можно узнать в этой статье.

Поддержка платформ

Дополнительную информацию о уровнях поддержки платформ в Rust можно найти на странице поддержки.

Стабилизированные API

Следующие API теперь можно использовать в контексте const:

Прочие изменения

Проверьте всё, что изменилось в Rust, Cargo и Clippy.

Кто работал над 1.89.0

Многие люди собрались вместе, чтобы создать Rust 1.89.0. Без вас мы бы не справились. Спасибо!

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

С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков.

Комментарии (1)


  1. Dhwtj
    09.08.2025 06:35

    Говорят, хотят стандартизировать асинхронность, чтобы меньше зависеть от tokio team (Amazon, Microsoft, ...)