Rust 新版解读 | 1.61 | 重点: 自定义 main 函数 ExitCode、const fn 增强、为锁定的 stdio 提供静态句柄

原文链接: https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html 翻译 by :AllanDowney

通过 rustup 安装的同学可以使用以下命令升级到 1.61 版本:

$ rustup update stable

支持自定义 main 函数 ExitCode

一开始, Rust main 函数只能返回单元类型 ()(隐式或显式),总是指示成功的退出状态,如果您要你想要其它的,必须调用 process::exit(code)。从 Rust 1.26 开始, main 允许返回一个 Result ,其中 Ok 转换为 C EXIT_SUCCESSErr 转换为 EXIT_FAILURE(也调试打印错误)。在底层,这些返回类型统一使用不稳定的 Termination 特征。

在此版本中,最终稳定了 Termination 特征,以及一个更通用的 ExitCode 类型,它封装了特定于平台的返回类型。它具有 SUCCESSFAILURE 常量,并为更多任意值实现 From<u8>。也可以为您自己的类型实现 Termination 特征,允许您在转换为 ExitCode 之前定制任何类型的报告。

例如,下面是一种类型安全的方式来编写 git bisect 运行脚本的退出代码:

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 {
        // Maybe print a message here
        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 中创建、传递和强制转换函数指针。例如,在为解释器构建编译时函数表时,这可能很有用。但是,仍然不允许调用 fn 指针。
  • 特征约束:现在可以将特征约束写在 const fn 的泛型参数上,如 T: Copy,以前只允许 Sized
  • dyn Trait 类型:类似地,const fn 现在可以处理特征对象 dyn Trait
  • impl Trait 类型:const fn 的参数和返回值现在可以是不透明的 impl Trait 类型。

注意,特征特性还不支持在 const fn 中调用这些特征的方法。

为锁定的 stdio 提供静态句柄

三种标准 I/O 流 —— StdinStdoutStderr —— 都有一个 锁(&self),允许对同步读写进行更多控制。但是,它们返回的锁守卫具有从 &self 借来的生命周期,因此它们被限制在原始句柄的范围内。这被认为是一个不必要的限制,因为底层锁实际上是在静态存储中,所以现在守卫返回一个 'static 生命期,与句柄断开连接。

例如,一个常见的错误来自于试图获取一个句柄并将其锁定在一个语句中:

#![allow(unused)]
fn main() {
// 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,而不是借用那个临时的,所以这个可以正常工作!