[Перевод] Rust 1.61.0: пользовательские коды возврата в main, расширение возможностей const fn и изменение IO-блокировок

7c7ec050705eb758563b65df0c856d50

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

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

rustup update stable

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

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


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


Пользовательские коды возврата из main

Изначально функция main могла возвращать только unit-тип () (неважно, явно или неявно), всегда обозначая удачное завершение программы. Таким образом, чтобы сообщить о неудаче, вы могли вызвать process::exit(code). Начиная с Rust 1.26, main позволяет возвращать Result, в котором Ok транслируется в С-константу EXIT_SUCCESS, а Err — в EXIT_FAILURE (при этом в отладочном виде также выводится сообщение об ошибке). Под капотом эти разные возвращаемые типы были объединены под нестабильным типажом Termination.

В этом выпуске был стабилизирован типаж Termination и более общий тип ExitCode, который абстрагирует платформо-зависимые коды возврата. У него есть константы SUCCESS и FAILURE, а также реализация From для произвольных значений. Типаж Termination также может быть реализован для ваших типов, позволяя представлять разные виды сообщений до преобразования их в ExitCode.

Для примера здесь представлен типобезопасный вариант написания кодов возврата для git bisect run:

use std::process::{ExitCode, Termination};

#[repr(u8)]
pub enum GitBisectResult {
    Good = 0,
    Bad = 1,
    Skip = 125,
    Abort = 255,
}

impl Termination for GitBisectResult {
    fn report(self) -> ExitCode {
        // Здесь можно вывести сообщение
        ExitCode::from(self as u8)
    }
}

fn main() -> GitBisectResult {
    std::panic::catch_unwind(|| {
        todo!("test the commit")
    }).unwrap_or(GitBisectResult::Abort)
}


Больше возможностей для const fn

Несколько инкрементальных особенностей было стабилизировано в этом выпуске для предоставления большей функциональности const функций:


  • Базовая обработка fn указателей: теперь вы можете создавать, передавать и преобразовывать указатели на функции в const fn. Например, это будет удобно использовать для интерпретаторов при создании таблиц функций во время сборки. Однако пока что не разрешается такие указатели вызывать.


  • Ограничения типажей: теперь вы можете написать для const fn ограничения типажей в обобщённых параметрах, таких как T: Copy, где ранее было разрешено только Sized.


  • dyn Trait типы: аналогично, const fn теперь может работать с трейт-объектами dyn Trait.


  • impl Trait типы: аргументы и возвращаемое значение const fn теперь могут быть непрозрачным impl Trait типом.


Обратите внимание, что возможности для типажей не позволяют вызывать их методы в const fn.

Для получения более подробной информации о текущем состоянии возможностей для const контекста смотрите раздел Constant Evaluation справочника. Также новые возможности можно отслеживать в rust#57563.


Обработчики блокировки stdio с временем жизни 'static

Каждый из трёх стандартных потоков ввода-вывода Stdin, Stdout и Stderr имеет метод lock(&self), позволяющий получить больший контроль над синхронизацией чтения и записи. Однако они возвращают ограничители блокировки со временем жизни, полученным от &self, из-за чего те ограничены областью видимости исходного метода. Было определено, что это ненужное ограничение, так как нижележащие блокировки находятся в статическом хранилище. Поэтому теперь ограничители возвращаются с временем жизни 'static, отвязываясь от оригинального метода.

Например, общая ошибка, получаемая при попытке захватить управление и блокировку в одном выражении:

// error[E0716]: temporary value dropped while borrowed
let out = std::io::stdout().lock();
//        ^^^^^^^^^^^^^^^^^       - temporary value is freed at the end of this statement
//        |
//        creates a temporary which is freed while still in use

Теперь ограничитель блокировки стал 'static и не создаёт временного заимствования, так что этот код будет работать!


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

Стабилизированы следующие методы и реализации типажей:

Следующие ранее стабилизированные API стали const:


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

В выпуске Rust 1.61.0 есть и другие изменения: узнайте, что изменилось в Rust, Cargo и Clippy.

В следующем выпуске мы планируем повысить минимальные требования для ядра Linux до версии 3.2 и для glibc до 2.17. Будем рады получить вашу обратную связь в rust#95026.


Участники 1.61.0

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


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

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

Данную статью совместными усилиями перевели andreevlex, TelegaOvoshey и funkill.

© Habrahabr.ru