Rust 1.60.0版本的新功能介绍

256 阅读2分钟

Rust团队很高兴地宣布Rust的新版本,即1.60.0。Rust是一种编程语言,使每个人都能建立可靠和高效的软件。

如果你已经通过rustup安装了以前的Rust版本,你可以用1.60.0获得:

rustup update stable

如果你还没有,你可以从我们网站的相应页面获得rustup,并在GitHub上查看1.60.0的详细发布说明。如果你想通过测试未来的版本来帮助我们,你可以考虑在本地更新,使用测试频道(rustup default beta )或夜间频道(rustup default nightly )。请报告你可能遇到的任何bug!

1.60.0稳定版中的内容

基于源代码的代码覆盖

rustc中对基于LLVM的覆盖仪的支持已经稳定下来。你可以在你的代码上尝试一下,用-Cinstrument-coverage ,例如像这样重建你的代码:

RUSTFLAGS="-C instrument-coverage" cargo build

之后,你可以运行生成的二进制文件,它将在当前目录下产生一个default.profraw 文件。(路径和文件名可以被环境变量覆盖,详见文档)。

llvm-tools-preview 组件包括:llvm-profdata ,用于处理和合并原始剖面输出(覆盖区域执行计数);以及llvm-cov,用于生成报告。llvm-cov ,结合处理后的输出,来自llvm-profdata ,以及二进制文件本身,因为二进制文件嵌入了一个从计数器到实际源代码区域的映射关系:

rustup component add llvm-tools-preview
$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse default.profraw -o default.profdata
$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov show -Xdemangler=rustfilt target/debug/coverage-testing \
    -instr-profile=default.profdata \
    -show-line-counts-or-regions \
    -show-instantiations

在一个简单的helloworld二进制文件上的上述命令产生了这个带注释的报告,显示了输入的每一行都被覆盖:

    1|      1|fn main() {
    2|      1|    println!("Hello, world!");
    3|      1|}

更多细节,请阅读rustc书中的文档。基线功能是稳定的,并将以某种形式存在于所有未来的Rust版本中,但具体的输出格式和产生它的LLVM工具可能会改变。由于这个原因,必须确保你使用的llvm-tools-preview 和用于编译代码的rustc二进制文件是同一个版本。

cargo --timings

Cargo已经稳定地支持用--timings 标志来收集构建信息:

$ cargo build --timings
   Compiling hello-world v0.1.0 (hello-world)
      Timing report saved to target/cargo-timings/cargo-timing-20220318T174818Z.html
    Finished dev [unoptimized + debuginfo] target(s) in 0.98s

该报告也被复制到了target/cargo-timings/cargo-timing.html 。关于Cargo的发行版构建的报告已经放在这里了。这些报告对提高构建性能很有帮助。 关于定时报告的更多信息可以在文档中找到。

Cargo功能的新语法

这个版本引入了两个新的变化,以改善对Cargo特性的支持,以及它们与可选依赖关系的交互方式。命名的依赖性和弱依赖性特性。

长期以来,Cargo一直支持功能与可选依赖关系,如下所示:

[dependencies]
jpeg-decoder = { version = "0.1.20", default-features = false, optional = true }

[features]
# Enables parallel processing support by enabling the "rayon" feature of jpeg-decoder.
parallel = ["jpeg-decoder/rayon"]

在这个例子中,有两件事需要注意:

  • 可选的依赖关系jpeg-decoder ,隐含地定义了一个同名的特性。启用jpeg-decoder 功能将启用jpeg-decoder 依赖关系。
  • "jpeg-decoder/rayon" 语法启用了jpeg-decoder 依赖关系启用了jpeg-decoder 依赖关系的rayon 特性。

命名功能解决了第一个问题。现在你可以在[features] 表中使用dep: 前缀来明确引用一个可选的依赖关系,而不隐含地将其作为一个特性公开。这让你在如何定义与可选依赖关系相对应的特性方面有更多的控制权,包括将可选依赖关系隐藏在更具描述性的特性名称后面。

弱依赖性特性解决了第二个问题,即"optional-dependency/feature-name" 语法总是会启用optional-dependency 。然而,往往只有在其他功能启用了可选依赖的情况下,你才想启用该功能。从1.60版本开始,你可以像"package-name?/feature-name" 中那样添加一个"?",只有在其他东西启用了可选依赖关系时才会启用给定的功能。

例如,假设我们在库中添加了一些序列化支持,这需要在一些可选的依赖中启用相应的功能。这可以这样做:

[dependencies]
serde = { version = "1.0.133", optional = true }
rgb = { version = "0.8.25", optional = true }

[features]
serde = ["dep:serde", "rgb?/serde"]

在这个例子中,启用serde特性将启用serde依赖关系。它也将启用 rgb 依赖关系的 serde 特性,但只有在其他东西启用了 rgb 依赖关系的情况下。

递增编译状态

1.60版本重新启用了增量编译功能。Rust团队继续致力于修复增量编译中的错误,但目前还没有发现导致大范围破坏的问题,所以我们选择重新启用增量编译。此外,编译器团队正在继续研究长期策略,以避免未来出现这类问题。这个过程还处于相对早期的阶段,所以我们在这方面还没有什么可以分享的。

Instant 单调性保证

在所有的平台上,Instant ,如果可用的话,将尝试使用保证单调性行为的操作系统API(在所有一级平台上都是如此)。在实践中,这种保证--在极少数情况下--会被硬件、虚拟化或操作系统的错误所破坏。为了解决这些错误和不提供单调时钟的平台的问题,Instant::duration_since,Instant::elapsedInstant::sub 现在饱和度为零。在较早的Rust版本中,这反而导致了恐慌。Instant::checked_duration_since ,可以用来检测和处理违反单调性的情况,或者Instants以错误的顺序被减去。

这个变通方法掩盖了编程错误,即早期和晚期的实例被意外调换。出于这个原因,未来的Rust版本可能至少在这些情况下重新引入恐慌,如果可能并且有效的话。

在1.60之前,单调性的保证是通过std中的mutexes或atomics提供的,这可能会给Instant::now() 。此外,恐慌行为意味着Rust软件可以在一个子集的环境中恐慌,这在很大程度上是不可取的,因为该软件的作者可能无法修复或升级他们所运行的操作系统、硬件或虚拟化系统。此外,在这些环境中引入意外的恐慌使得Rust软件的可靠性和可移植性降低,这比将单调的时钟处理中典型的无趣的平台错误暴露给终端用户更令人担忧。

稳定的API

以下方法和特性的实现现在已经稳定了:

其他变化

在Rust 1.60.0版本中还有其他变化。请查看RustCargoClippy中的变化。

1.60.0的贡献者

许多人共同创造了Rust 1.60.0,没有你们,我们不可能做到这一点。谢谢大家