Rust 1.21 发布

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

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

如果您已经安装了 Rust 的早期版本,那么获取 Rust 1.21 非常简单,只需执行以下命令:

$ rustup update stable

如果您还没有安装 Rust,您可以从我们网站上的相应页面获取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;

在这里,由于 FIVEstaticx 是一个 &'static i32。因此,这就是 Rust 现在在这种情况下会做的事情。有关详细信息,请参阅 RFC 1414,该 RFC 在 1 月份被接受,但始于 2015 年 12 月!

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

RLS 现在可以通过调用 rustup component add rls-preview 通过 rustup 安装。一般来说,许多有用的 Rust 开发工具(如 RLS、Clippy 和 rustfmt)都需要 nightly Rust;这是使它们在 stable 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 的各种 trait。 现在已为 Clone trait 修复了此问题,这有时也会导致许多 ICE,当类型是 Copy 而不是 Clone 时。对于其他 trait,最近接受了一个关于类型级整数的 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 trait 上的 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 crate 依赖于 bar crate,我们在 bar 中发现了一个 bug。为了测试这一点,我们将下载 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。没有大家,我们不可能做到这一点。谢谢!