宣布 Rust 1.21

2017 年 10 月 12 日 · Rust 核心团队

Rust 团队很高兴宣布 Rust 的最新版本 1.21.0。Rust 是一种系统编程语言,专注于安全、速度和并发。

如果你已经安装了旧版本的 Rust,获取 Rust 1.21 非常简单

$ rustup update stable

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

1.21.0 稳定版的新功能

此版本包含一些非常小的但很实用的功能,以及一些新的文档。

首先,对字面量进行了一些小的更改。考虑以下代码

let x = &5;

在 Rust 中,这段代码等同于

let _x = 5;
let x = &_x;

也就是说,这里的 5 将存储在堆栈上,或者可能存储在寄存器中。x 将是它的引用。

但是,鉴于它是一个字面量整数,它没有必要像这样局部化。假设我们有一个接受 'static 参数的函数,比如 std::thread::spawn。你可能会像这样使用 x

use std::thread;

fn main() {
    let x = &5;

    thread::spawn(move || {
        println!("{}", x);
    });

}

在之前的 Rust 版本中,这将无法编译

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:4:14
   |
4  |     let x = &5;
   |              ^ does not live long enough
...
10 | }
   | - temporary value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

因为 5 是局部的,所以它的借用也是局部的,这不能满足 spawn 的要求。

但是,如果你在 Rust 1.21 上编译这段代码,它将可以正常工作。为什么呢?如果被引用的东西可以放入 static 中,我们可以像这样对 let x = &5; 进行反糖化

static FIVE: i32 = 5;

let x = &FIVE;

在这里,由于 FIVEstatic 的,所以 x 是一个 &'static i32。因此,Rust 将在这种情况中执行此操作。有关完整详细信息,请参阅RFC 1414,该 RFC 于 1 月份被接受,但早在 2015 年 12 月就已开始!

我们现在在生成代码时并行运行 LLVM,这应该可以减少峰值内存使用量。

RLS 现在可以通过rustup 安装,方法是调用 rustup component add rls-preview。一般来说,许多有用的 Rust 开发工具,如 RLS、Clippy 和 rustfmt 需要 nightly Rust;这是让它们在稳定版 Rust 上运行的第一步。请查看预览版,你将在未来听到更多关于这些计划的消息。

最后,一些文档改进。首先,如果你访问std::os 的文档,其中包含特定于操作系统的功能,你将不再只看到 linux,即我们构建文档的平台。我们一直很遗憾托管版本的文档一直是特定于 Linux 的;这是朝着纠正这一问题迈出的第一步。这是特定于标准库的,而不是通用的;我们希望在未来进一步改进这一点。

接下来,Cargo 的文档正在迁移! 历史上,Cargo 的文档托管在 doc.crates.io 上,它不遵循发布火车模型,即使 Cargo 本身遵循。这导致了这样的情况:一个功能会在 Cargo nightly 中出现,文档会更新,然后在长达 12 周的时间里,用户会认为它应该可以工作,但实际上却不能。 https://doc.rust-lang.net.cn/cargo 将成为 Cargo 文档的新家,不过目前,该 URL 是指向 doc.crates.io 的重定向。未来的版本将迁移 Cargo 的文档,届时 doc.crates.io 将重定向到 doc.rust-lang.org/cargo。Cargo 的文档长期以来一直需要更新,所以预计在未来会听到更多关于 Cargo 文档的新闻!

最后,到目前为止,rustdoc 没有任何文档。现在这个问题已经得到解决,并提供了一本新的“rustdoc 手册”,位于https://doc.rust-lang.net.cn/rustdoc。这些文档目前还比较简陋,但我们会随着时间的推移不断改进它们。

查看详细的发布说明以了解更多信息。

库稳定化

此版本没有太多稳定化,但有一个非常棒的体验改进:由于缺乏类型级整数,数组只支持大小不超过 32 的各种特征。这个问题现在已经针对 Clone 特征得到解决,这也导致了在某些情况下出现很多 ICE,当类型是 Copy 但不是 Clone 时。对于其他特征,最近接受了关于类型级整数的 RFC,这可能有助于解决这种情况。但是,该更改尚未实施,尽管目前正在进行先决条件工作。

接下来,Iterator::for_each 已稳定,允许你使用迭代器进行副作用,而无需使用 for 循环

// old
for i in 0..10 {
    println!("{}", i);
}

// new
(0..10).for_each(|i| println!("{}", i));

使用哪一个取决于你的情况;在上面的示例中,for 循环非常简单。但是,当你将多个迭代器链接在一起时,for_each 版本有时更清晰。考虑以下情况

// old
for i in (0..100).map(|x| x + 1).filter(|x| x % 2 == 0) {
    println!("{}", i);
}

// new
(0..100)
    .map(|x| x + 1)
    .filter(|x| x % 2 == 0)
    .for_each(|i| println!("{}", i));

Rc<T>Arc<T> 现在实现了 From<&[T]> where T: CloneFrom<str>From<String>From<Box<T>> where T: ?SizedFrom<Vec<T>>

Ord 特征上的maxmin 函数 现在已稳定。

needs_drop 内在函数 现在已稳定。

最后,std::mem::discriminant 已稳定,允许你查看 enum 实例是什么变体,而无需使用 match 语句。

查看详细的发布说明以了解更多信息。

Cargo 功能

除了上面列出的文档功能之外,Cargo 在此版本中增加了一项主要功能:[patch]。在RFC 1969 中设计,Cargo.toml[patch] 部分可以在你想要覆盖依赖关系图的某些部分时使用。我们还有一个功能 [replace],它具有类似的功能。在很多方面,[patch] 是新的 [replace],虽然我们没有计划弃用或删除 [replace],但在这一点上,你应该使用 [patch] 而不是 [replace]

那么它看起来像什么?假设我们有一个 Cargo.toml,它看起来像这样

[dependencies]
foo = "1.2.3"

此外,我们的 foo 箱子依赖于 bar 箱子,我们发现 bar 中存在一个错误。为了测试这一点,我们将下载 bar 的源代码,然后更新我们的 Cargo.toml

[dependencies]
foo = "1.2.3"

[patch.crates-io]
bar = { path = '/path/to/bar' }

现在,当你 cargo build 时,它将使用 bar 的本地版本,而不是 foo 依赖于 crates.io 上的版本。

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

此外

查看详细的发布说明以了解更多信息。

1.21.0 的贡献者

许多人共同创建了 Rust 1.21。没有你们,我们无法做到。 感谢!