Rust 团队很高兴地宣布 Rust 新版本 1.60.0 发布。Rust 是一种编程语言,旨在赋能所有人构建可靠且高效的软件。
如果您之前通过 rustup 安装了 Rust,可以使用以下命令获取 1.60.0 版本:
$ rustup update stable
如果您尚未安装,可以从我们的网站上的相应页面获取 rustup
,并查看 GitHub 上 1.60.0 版本的详细发布说明。如果您想通过测试未来的版本来帮助我们,您可以考虑将本地更新到 beta 频道 (rustup default beta
) 或 nightly 频道 (rustup default nightly
)。请报告您可能遇到的任何错误!
1.60.0 稳定版的新特性
基于源代码的代码覆盖率
rustc 中已经稳定了对基于 LLVM 的覆盖率检测的支持。您可以通过使用 -Cinstrument-coverage
重新构建代码来尝试此功能,例如像这样:
RUSTFLAGS="-C instrument-coverage" cargo build
之后,您可以运行生成的二进制文件,这将在当前目录中生成一个 default.profraw
文件。(路径和文件名可以通过环境变量覆盖;详情请参阅 文档)。
llvm-tools-preview
组件包含 llvm-profdata
,用于处理和合并原始 profile 输出(覆盖区域执行计数);以及 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 book 中的文档。基线功能是稳定的,并且将在所有未来的 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 发布版本的报告已发布在这里。这些报告对于提高构建性能很有用。有关 timing 报告的更多信息,请参阅文档。
Cargo features 的新语法
此版本引入了两项新更改,以改进对 Cargo features 以及它们如何与 可选依赖项 交互的支持:命名空间依赖项和弱依赖项 features。
Cargo 长期以来一直支持 features 以及可选依赖项,如下面的代码片段所示。
[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
隐式定义了一个同名的 feature。启用jpeg-decoder
feature 将启用jpeg-decoder
依赖项。 "jpeg-decoder/rayon"
语法启用jpeg-decoder
依赖项并且启用jpeg-decoder
依赖项的rayon
feature。
命名空间 features 解决了第一个问题。您现在可以在 [features]
表中使用 dep:
前缀来显式引用可选依赖项,而无需隐式将其公开为 feature。 这使您可以更好地控制如何定义与可选依赖项对应的 feature,包括将可选依赖项隐藏在更具描述性的 feature 名称之后。
弱依赖项 features 解决了第二个问题,即 "optional-dependency/feature-name"
语法始终会启用 optional-dependency
。但是,通常您只想在某些其他 feature 启用了可选依赖项的情况下,才启用可选依赖项上的 feature。从 1.60 版本开始,您可以添加一个 ?
,如 "package-name?/feature-name"
,这将仅在其他内容启用了可选依赖项的情况下启用给定的 feature。
例如,假设我们为我们的库添加了一些序列化支持,它需要启用某些可选依赖项中的相应 feature。可以像这样完成:
[dependencies]
serde = { version = "1.0.133", optional = true }
rgb = { version = "0.8.25", optional = true }
[features]
serde = ["dep:serde", "rgb?/serde"]
在此示例中,启用 serde feature 将启用 serde 依赖项。它还将为 rgb 依赖项启用 serde feature,但前提是其他内容已启用 rgb 依赖项。
增量编译状态
增量编译已在 1.60 版本中重新启用。Rust 团队将继续致力于修复增量编译中的错误,但目前尚不清楚是否存在导致广泛破坏的问题,因此我们选择重新启用增量编译。此外,编译器团队正在继续研究长期策略,以避免将来出现此类问题。该过程尚处于早期阶段,因此我们目前没有任何可以分享的内容。
Instant
单调性保证
在所有平台上,Instant
将尝试使用操作系统 API,如果可用,该 API 可保证单调行为(在所有 Tier 1 平台上都是如此)。实际上,这种保证在罕见的情况下会被硬件、虚拟化或操作系统错误破坏。为了解决这些错误和不提供单调时钟的平台,Instant::duration_since
、Instant::elapsed
和 Instant::sub
现在饱和到零。在旧版本的 Rust 中,这会导致 panic。Instant::checked_duration_since
可用于检测和处理违反单调性的情况,或者 Instant
以错误的顺序相减的情况。
这种解决方法掩盖了意外交换较早和较晚 instant 的编程错误。因此,如果可能且高效,未来的 Rust 版本可能会在至少这些情况下重新引入 panic。
在 1.60 之前,单调性保证是通过 std 中的互斥锁或原子操作提供的,这可能会给 Instant::now()
带来很大的性能开销。此外,panic 行为意味着 Rust 软件可能会在一部分环境中 panic,这在很大程度上是不希望看到的,因为该软件的作者可能无法修复或升级他们正在运行的操作系统、硬件或虚拟化系统。此外,在这些环境中引入意外的 panic 会使 Rust 软件的可靠性和可移植性降低,这比向最终用户暴露通常不重要的单调时钟处理中的平台错误更令人担忧。
稳定的 API
以下方法和 trait 实现现在已稳定:
Arc::new_cyclic
Rc::new_cyclic
slice::EscapeAscii
<[u8]>::escape_ascii
u8::escape_ascii
Vec::spare_capacity_mut
MaybeUninit::assume_init_drop
MaybeUninit::assume_init_read
i8::abs_diff
i16::abs_diff
i32::abs_diff
i64::abs_diff
i128::abs_diff
isize::abs_diff
u8::abs_diff
u16::abs_diff
u32::abs_diff
u64::abs_diff
u128::abs_diff
usize::abs_diff
io::ErrorKind 的 Display 实现
ExitCode 的 From<u8> 实现
!
( "never" 类型) 的 Not 实现- Op
Assign<$t> for Wrapping<$t>
arch::is_aarch64_feature_detected!
其他更改
Rust 1.60.0 版本还有其他更改。请查看 Rust、Cargo 和 Clippy 中的更改。
1.60.0 版本的贡献者
许多人齐心协力创建了 Rust 1.60.0。没有你们所有人,我们不可能做到。谢谢!