Rust 1.87.0 и 10 лет Rust!


Команда Rust празднует 10-летие Rust в Утрехте, Нидерланды, и рада сообщить о новой версии языка — 1.87.0!



Сегодняшний день релиза выпал на 10-летний юбилей выхода Rust 1.0!


Спасибо мириадам участников, кто работал или работает над Rust. Выпьем за ещё многие десятилетия впереди! 🎉




Как обычно, новая версия включает в себя все изменения, которые были внесены в бета-версию за последние шесть недель согласно последовательному и регулярному циклу выпуска. Мы следуем ему начиная с Rust 1.0.


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


$ rustup update stable

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


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


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


Анонимные конвейеры


1.87 даёт доступ из стандартной библиотеки к анонимным каналам, включая интеграцию с методами ввода/вывода std::process::Command. Например, объединить stdout и stderr в один поток теперь относительно просто, в то время как раньше необходимо было использовать разные потоки или платформо-специфические функции.


use std::process::Command;
use std::io::Read;

let (mut recv, send) = std::io::pipe()?;

let mut command = Command::new("path/to/bin")
    // И stdout, и stderr теперь пишут в один канал.
    .stdout(send.try_clone()?)
    .stderr(send)
    .spawn()?;

let mut output = Vec::new();
recv.read_to_end(&mut output)?;

// Обратите внимание, что что мы читаем из канала до завершения процесса, для исключения
// переполнения буфера ОС, если программа создаст очень много вывода.
assert!(command.wait()?.success());

Безопасные архитектурные интринсики


Большинство интринсиков из std::arch, которые небезопасны только из-за того, что требуют включения таргет-фич, теперь могут быть вызваны из безопасного кода, в котором эти фичи включены. Например, следующая программа, реализующая суммирование элементов массива с использованием ручных интринсиков, теперь использует безопасный код в основном цикле.


#![forbid(unsafe_op_in_unsafe_fn)]

use std::arch::x86_64::*;

fn sum(slice: &[u32]) -> u32 {
    #[cfg(target_arch = "x86_64")]
    {
        if is_x86_feature_detected!("avx2") {
            // БЕЗОПАСНОСТЬ: Во время работы мы удостоверились, что необходимая функциональность присутствует,
            // так что вызывать эту функицю безопасно.
            return unsafe { sum_avx2(slice) };
        }
    }

    slice.iter().sum()
}

#[target_feature(enable = "avx2")]
#[cfg(target_arch = "x86_64")]
fn sum_avx2(slice: &[u32]) -> u32 {
    // БЕЗОПАСНОСТЬ: __m256i и u32 одинаково валидны.
    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };

    let mut sum = prefix.iter().sum::<u32>();
    sum += tail.iter().sum::<u32>();

    // Основной цикл теперь полностью состоит из безопасного кода, потому что интринсики, требующие таргет фичу (avx2),
    // упакованы в саму функцию.
    let mut base = _mm256_setzero_si256();
    for e in middle.iter() {
        base = _mm256_add_epi32(base, *e);
    }

    // БЕЗОПАСНОСТЬ: __m256i и u32 одинаково валидны.
    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
    sum += base.iter().sum::<u32>();

    sum
}

asm! прыжки в Rust-код


Встроенный ассемблер (asm!) теперь может прыгать в помеченные участки Rust-кода. Это делает более гибким низкоуровневое программирование — например, реализацию оптимизированного контроля управления в ядрах ОС или более эффективное взаимодействие с железом.


  • Макрос asm! теперь поддерживает операнд label, который работает как переход к метке
  • Метка должна быть блочным выражением с возвращаемым типом () или !
  • Блок выполняется, когда на него совершается прыжок. Выполнение продолжается после блока asm!.
  • Использование операндов output и label в одном вызове asm! остаётся unstable.

unsafe {
    asm!(
        "jmp {}",
        label {
            println!("Выскочил из asm!");
        }
    );
}

Больше информации можно найти в reference.


Прецизионный захват (+ use<...>) в impl Trait в объявлении трейтов


В этом выпуске стабилизировано указание конкретных захваченных обобщённых типов и времён жизни в объявлениях трейтов с использованием возвращаемых типов impl Trait. Благодаря чему теперь можно использовать эту функцию в определениях трейтов, расширяя возможности стабилизации для функций, не связанных с трейтами, в 1.82.


Несколько примеров:


trait Foo {
    fn method<'a>(&'a self) -> impl Sized;

    // ... преобразуется во что-то вроде:
    type Implicit1<'a>: Sized;
    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;

    // ... а при прецезионном захвате ...
    fn precise<'a>(&'a self) -> impl Sized + use<Self>;

    // ... преобразуется во что-то подобное:
    type Implicit2: Sized;
    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
}

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



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



Удаление таргета i586-pc-windows-msvc


Таргет i586-pc-windows-msvc удалён из Tier 2. Отличие i586-pc-windows-msvc от более популярного таргета i686-pc-windows-msvc из Tier 1 в том, что i586-pc-windows-msvc не требует поддержки инструкций SSE2. Но Windows 10, минимально допустимая версия ОС для всех windows-таргетов (за исключением win7), сама по себе требует инструкций SSE2.


Все пользователи, использующие в качестве целевой платформы i586-pc-windows-msvc, должны мигрировать на i686-pc-windows-msvc.


Для большей информации вы можете изучить Major Change Proposal.


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


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


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


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


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


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