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 вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков.

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