Rust 1.42.0 发布公告

2020 年 3 月 12 日 · Rust 发布团队

Rust 团队很高兴地宣布 Rust 的新版本 1.42.0。Rust 是一种编程语言,旨在帮助每个人构建可靠且高效的软件。

如果您之前通过 rustup 安装了 Rust,则获取 Rust 1.42.0 非常容易,只需执行以下操作:

$ rustup update stable

如果您尚未安装,您可以从我们网站上的相应页面获取 rustup,并查看 GitHub 上 1.42.0 的详细发布说明

1.42.0 稳定版的新特性

Rust 1.42.0 的亮点包括:在 unwrap 时提供更有用的 panic 消息、子切片模式、弃用 Error::description 以及更多。请参阅详细发布说明,了解本文未涵盖的其他更改。

OptionResult panic 消息中更有用的行号

在 Rust 1.41.1 中,对 Option::None 值调用 unwrap() 会产生如下错误消息:

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /.../src/libcore/macros/mod.rs:15:40

类似地,由 unwrap_errexpectexpect_err 以及 Result 类型上的相应方法生成的 panic 消息中的行号也指向 core 内部。

在 Rust 1.42.0 中,所有这八个函数生成的 panic 消息都提供了调用它们的行号。新的错误消息如下所示:

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:2:5

这意味着对 unwrap 的无效调用发生在 src/main.rs 的第 2 行。

此行为是通过注解 #[track_caller] 实现的。此注解尚不可在稳定的 Rust 中使用;如果您有兴趣在自己的代码中使用它,可以通过关注 此跟踪 issue 来了解其进展。

子切片模式

在 Rust 1.26 中,我们稳定了“切片模式”,它允许您在切片上进行 match 匹配。它们看起来像这样:

fn foo(words: &[&str]) {
    match words {
        [] => println!("empty slice!"),
        [one] => println!("one element: {:?}", one),
        [one, two] => println!("two elements: {:?} {:?}", one, two),
        _ => println!("I'm not sure how many elements!"),
    }
}

这允许您在切片上进行匹配,但非常有限。您必须选择您希望支持的确切大小,并且必须有一个用于您不想支持的大小的 catch-all 分支。

在 Rust 1.42 中,我们扩展了对匹配切片部分的支持

fn foo(words: &[&str]) {
    match words {
        ["Hello", "World", "!", ..] => println!("Hello World!"),
        ["Foo", "Bar", ..] => println!("Baz"),
        rest => println!("{:?}", rest),
    }
}

.. 称为“rest pattern”(剩余模式),因为它匹配切片的其余部分。上面的示例在切片的末尾使用了剩余模式,但您也可以在其他方式中使用它:

fn foo(words: &[&str]) {
    match words {
        // Ignore everything but the last element, which must be "!".
        [.., "!"] => println!("!!!"),

        // `start` is a slice of everything except the last element, which must be "z".
        [start @ .., "z"] => println!("starts with: {:?}", start),

        // `end` is a slice of everything but the first element, which must be "a".
        ["a", end @ ..] => println!("ends with: {:?}", end),

        rest => println!("{:?}", rest),
    }
}

如果您有兴趣了解更多信息,我们发布了 一篇关于 Inside Rust 博客的文章,讨论了这些更改以及我们可能在未来引入稳定版的更多模式匹配改进!您还可以阅读 Thomas Hartmann 的文章,了解更多关于切片模式的信息。

matches!

此版本的 Rust 稳定了一个新的宏 matches!。此宏接受一个表达式和一个模式,如果模式与表达式匹配,则返回 true。换句话说:

// Using a match expression:
match self.partial_cmp(other) {
    Some(Less) => true,
    _ => false,
}

// Using the `matches!` macro:
matches!(self.partial_cmp(other), Some(Less))

您还可以使用 | 模式和 if guards 等功能:

let foo = 'f';
assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));

let bar = Some(4);
assert!(matches!(bar, Some(x) if x > 2));

use proc_macro::TokenStream; 现在可以工作了

在 Rust 2018 中,我们移除了对 extern crate 的需求。但是过程宏有点特殊,因此当您编写过程宏时,仍然需要说 extern crate proc_macro;

在此版本中,如果您使用 Cargo,在使用 2018 edition 时,您不再需要这一行;您可以像使用任何其他 crate 一样使用 use。鉴于大多数项目已经有一行类似于 use proc_macro::TokenStream; 的代码,此更改意味着您可以删除 extern crate proc_macro; 行,而您的代码仍然可以工作。这个更改很小,但使过程宏更接近常规代码。

稳定的 API

其他更改

Rust 1.42.0 版本还有其他更改:请查看 RustCargoClippy 中的更改。

兼容性说明

此版本有两个值得注意的兼容性说明:标准库中的弃用以及将 32 位 Apple 目标降级为 Tier 3 支持。

Error::Description 已被弃用

有时,会犯错误。Error::description 方法现在被认为是其中一个错误。问题在于其类型签名:

fn description(&self) -> &str

由于 description 返回 &str,因此它远没有我们希望的那么有用。这意味着您基本上需要逐字返回 Error 的内容;如果您想使用格式化来生成更友好的描述,那是不可能的:您需要返回一个 String。相反,错误类型应实现 Display/Debug traits 以提供错误的描述。

此 API 自 Rust 1.0 以来就已存在。我们为此目标努力了很长时间:早在 Rust 1.27 中,我们就“软弃用”了此方法。这在实践中意味着,我们为该函数提供了一个默认实现。这意味着用户在实现 Error trait 时不再被迫实现此方法。在此版本中,我们将其标记为实际弃用,并采取了一些步骤来在 Error 的文档中淡化该方法。由于我们的稳定性策略,description 永远不会被删除,因此这是我们能做的最大限度。

降级 32 位 Apple 目标

Apple 不再支持 32 位目标,因此,我们也不支持。该项目已将其降级为 Tier 3 支持。有关此事的更多详细信息,请查看 1 月份的 这篇文章,其中详细介绍了所有内容。

1.42.0 的贡献者

许多人齐心协力创建了 Rust 1.42.0。没有你们所有人,我们不可能做到。谢谢!