发布 Rust 1.59.0

2022年2月24日 · Rust 团队

Rust 团队发布了新版本 Rust 1.59.0。Rust 是一门赋予每个人构建可靠且高效软件能力的编程语言。


今天的发布恰逢普京军队突然入侵乌克兰而全世界都将注意力集中于此的日子。在详细介绍 Rust 新版本之前,我们想声明,我们与乌克兰人民站在一起,并向所有受这场冲突影响的人们表达我们的支持。


如果你之前通过 rustup 安装了 Rust 版本,你可以使用以下命令升级到 1.59.0:

$ rustup update stable

如果你还没有安装,可以从我们的网站获取 rustup,并在 GitHub 上查看1.59.0 的详细发布说明

1.59.0 stable 版本有什么?

内联汇编

Rust 语言现在支持内联汇编。这使得许多需要对其执行进行非常低级控制或访问专用机器指令的应用程序成为可能。

例如,在为 x86-64 目标编译时,你现在可以这样写:

use std::arch::asm;

// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
    asm!(
        "mov {tmp}, {x}",
        "shl {tmp}, 1",
        "shl {x}, 2",
        "add {x}, {tmp}",
        x = inout(reg) x,
        tmp = out(reg) _,
    );
}
assert_eq!(x, 4 * 6);

用于在 asm!global_asm! 宏中命名寄存器的格式字符串语法与 Rust 格式字符串中使用的语法相同,因此 Rust 程序员应该会感到非常熟悉。

内联汇编可用的汇编语言和指令因目标架构而异。目前,Rust 稳定版编译器支持在以下架构上进行内联汇编:

  • x86 和 x86-64
  • ARM
  • AArch64
  • RISC-V

你可以在Rust By Example中看到更多内联汇编的示例,并在参考手册中找到更详细的文档。

解构赋值

你现在可以使用元组、切片和结构体模式作为赋值语句的左侧。

let (a, b, c, d, e);

(a, b) = (1, 2);
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5, f: 3 };

assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);

这使得赋值与长期以来支持相同功能的 let 绑定更加一致。请注意,不支持带有 += 等运算符的解构赋值。

常量泛型默认值和交错

泛型类型现在可以为其常量泛型指定默认值。例如,你现在可以这样写:

struct ArrayStorage<T, const N: usize = 2> {
    arr: [T; N],
}

impl<T> ArrayStorage<T> {
    fn new(a: T, b: T) -> ArrayStorage<T> {
        ArrayStorage {
            arr: [a, b],
        }
    }
}

以前,类型参数必须放在所有常量参数之前。现在放宽了这项限制,你可以将它们交错排列。

fn cartesian_product<
    T, const N: usize,
    U, const M: usize,
    V, F
>(a: [T; N], b: [U; M], f: F) -> [[V; N]; M]
where
    F: FnMut(&T, &U) -> V
{
    // ...
}

未来不兼容警告

有时 Rust 编译器中的错误会导致它接受不应该接受的代码。其中一个例子是安全代码中允许借用 packed struct 字段

尽管这种情况很少发生,但当你的项目使用的 crate 包含的代码在未来的版本中不再允许时,这可能会造成很大的干扰。实际上,你可能直到你的项目莫名其妙地停止构建时才会注意到!

当一个依赖项在未来的 Rust 版本中将被拒绝时,Cargo 现在会显示警告。运行 cargo buildcargo check 后,你可能会看到:

warning: the following packages contain code that will be rejected by a future version of Rust: old_dep v0.1.0
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`

你可以运行警告中提到的 cargo report 命令,查看将被拒绝的代码的完整报告。这给了你时间在依赖项导致你的构建失败之前升级它。

创建已 stripping 的二进制文件

从你分发的二进制文件中 stripping 掉不必要的信息(如 debuginfo)通常很有用,这可以减小文件大小。

虽然一直可以在创建二进制文件后手动进行 stripping,但 cargo 和 rustc 现在支持在链接时进行 stripping。要启用此功能,请在你的 Cargo.toml 中添加以下内容:

[profile.release]
strip = "debuginfo"

这将导致从 release 二进制文件中 stripping 掉 debuginfo。你也可以提供 "symbols" 或直接 true 来 stripping 掉所有支持的符号信息。

标准库通常包含 debug 符号和行级 debuginfo,因此默认情况下,即使构建 Rust 二进制文件时未启用 debug 符号,它仍然包含标准库的 debug 信息。使用 strip 选项可以让你移除这些额外信息,生成更小的 Rust 二进制文件。

有关更多详细信息,请参阅Cargo 的文档

默认关闭增量编译

1.59.0 版本默认禁用增量编译(除非通过环境变量显式开启:RUSTC_FORCE_INCREMENTAL=1)。这缓解了一个已知 bug #94124 的影响,该 bug 在开启增量编译时可能导致编译期间出现反序列化错误(和 panic)。

#94124 的具体修复已合并,目前位于 1.60 beta 版本中,该版本将在六周后发布。我们目前不知道还有其他问题会促使在 1.60 stable 中禁用增量编译的决定,如果 没有出现其他问题,1.60 stable 很可能会重新启用增量编译。在 beta 和 nightly 通道中,增量编译仍然默认开启。

一如既往,我们鼓励用户在 nightly 和 beta 通道上进行测试并报告你发现的问题:特别是对于增量 bug,这是确保 Rust 团队能够判断是否存在破坏性以及影响用户数量的最佳方式。

稳定的 API

以下方法和 trait 实现现已稳定:

以下之前稳定的函数现在是 const

其他更改

Rust 1.59.0 版本中还有其他更改。查看RustCargoClippy 中有哪些变化。

1.59.0 的贡献者

许多人共同努力创建了 Rust 1.59.0。没有你们所有人,我们不可能做到。谢谢!