You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

71 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Rust 新版解读 | 1.61 | 重点: 自定义 main 函数 ExitCode、const fn 增强、为锁定的 stdio 提供静态句柄
> 原文链接: https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html
> 翻译 by [AllanDowney](https://github.com/AllanDowney)
通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.61 版本:
```shell
$ rustup update stable
```
## 支持自定义 main 函数 ExitCode
一开始, Rust `main` 函数只能返回单元类型 `()`(隐式或显式),总是指示成功的退出状态,如果您要你想要其它的,必须调用 `process::exit(code)`。从 Rust 1.26 开始, `main` 允许返回一个 `Result` ,其中 `Ok` 转换为 `C EXIT_SUCCESS``Err` 转换为 `EXIT_FAILURE`(也调试打印错误)。在底层,这些返回类型统一使用不稳定的 `Termination` 特征。
在此版本中,最终稳定了 `Termination` 特征,以及一个更通用的 `ExitCode` 类型,它封装了特定于平台的返回类型。它具有 `SUCCESS``FAILURE` 常量,并为更多任意值实现 `From<u8>`。也可以为您自己的类型实现 `Termination` 特征,允许您在转换为 `ExitCode` 之前定制任何类型的报告。
例如,下面是一种类型安全的方式来编写 `git bisect` 运行脚本的退出代码:
```rust
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 流 —— `Stdin` 、`Stdout` 和 `Stderr` —— 都有一个 `锁(&self)`,允许对同步读写进行更多控制。但是,它们返回的锁守卫具有从 `&self` 借来的生命周期,因此它们被限制在原始句柄的范围内。这被认为是一个不必要的限制,因为底层锁实际上是在静态存储中,所以现在守卫返回一个 `'static` 生命期,与句柄断开连接。
例如,一个常见的错误来自于试图获取一个句柄并将其锁定在一个语句中:
```rust
// 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`,而不是借用那个临时的,所以这个可以正常工作!