发布 Rust 1.20

2017 年 8 月 31 日 · Rust 核心团队

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

如果您安装了之前的 Rust 版本,升级到 Rust 1.20 非常简单,只需运行

$ rustup update stable

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

1.20.0 stable 中有什么新特性

在之前的 Rust 版本中,您已经可以定义带有“关联函数”的 trait、结构体和枚举

struct Struct;

impl Struct {
    fn foo() {
        println!("foo is an associated function of Struct");
    }
}

fn main() {
    Struct::foo();
}

这些被称为“关联函数”是因为它们是与类型关联的函数,也就是说,它们附加到类型本身,而不是任何特定的实例上。

Rust 1.20 还增加了定义“关联常量”的能力

struct Struct;

impl Struct {
    const ID: u32 = 0;
}

fn main() {
    println!("the ID of Struct is: {}", Struct::ID);
}

也就是说,常量 IDStruct 关联。与函数一样,关联常量也适用于 trait 和枚举。

Trait 使用关联常量时拥有一项额外的能力,这赋予它们额外的力量。对于 trait,您可以使用关联常量,就像使用关联类型一样:通过声明它,但不赋予它值。trait 的实现者随后在实现时声明它的值

trait Trait {
    const ID: u32;
}

struct Struct;

impl Trait for Struct {
    const ID: u32 = 5;
}

fn main() {
    println!("{}", Struct::ID);
}

在此版本之前,如果您想创建一个表示浮点数的 trait,您必须这样写

trait Float {
    fn nan() -> Self;
    fn infinity() -> Self;
    ...
}

这有点笨拙,更重要的是,由于它们是函数,即使它们只返回一个常量,也不能在常量表达式中使用。因此,Float 的设计也必须包含常量

mod f32 {
    const NAN: f32 = 0.0f32 / 0.0f32;
    const INFINITY: f32 = 1.0f32 / 0.0f32;

    impl Float for f32 {
        fn nan() -> Self {
            f32::NAN
        }
        fn infinity() -> Self {
            f32::INFINITY
        }
    }
}

关联常量让您以更简洁的方式做到这一点。这个 trait 定义

trait Float {
    const NAN: Self;
    const INFINITY: Self;
    ...
}

会得到这个实现

mod f32 {
    impl Float for f32 {
        const NAN: f32 = 0.0f32 / 0.0f32;
        const INFINITY: f32 = 1.0f32 / 0.0f32;
    }
}

更简洁,也更通用。

关联常量是在 RFC 195 中提出的,几乎是三年前的事了。这个特性已经等待了很长时间!该 RFC 包含了所有关联项,而不仅仅是常量,因此其中一些,比如关联类型,实现得比其他的快。总的来说,我们在常量求值方面做了很多内部工作,以增强 Rust 的编译期元编程能力。未来在这方面会有更多进展。

我们还修复了文档测试中 include! 宏的一个 bug:对于相对路径,它错误地相对于工作目录,而不是当前文件。

有关更多信息,请参阅详细发行说明

库方面的稳定化

此版本在库方面没有*特别*令人兴奋的新特性,只是一些稳固的改进和 API 的持续稳定化。

unimplemented!现在接受消息,让您可以说明为什么某个功能尚未实现。

我们升级到 Unicode 10.0.0

浮点类型的 minmax用 Rust 重写,不再依赖于 cmath

此版本提供了针对 Stack Clash 漏洞的缓解措施,特别是堆栈探测(stack probes),以及在 Linux 上跳过主线程的手动堆栈保护(manual stack guard)。除了使用 Rust 1.20 之外,您无需进行任何操作即可获得这些保护。

我们在标准库中添加了一组新的排序函数:slice::sort_unstable_by_keyslice::sort_unstable_byslice::sort_unstable。您会注意到这些函数名称中都包含“unstable”(不稳定)。稳定性是排序算法的一个特性,对您来说可能重要也可能不重要,但现在您有了两种选择!下面是一个简要总结:假设我们有这样一个单词列表

rust
crate
package
cargo

这些单词中,cargocrate 都以字母 c 开头。仅按第一个字母排序的稳定排序必须产生这个结果

crate
cargo
package
rust

也就是说,因为在原始列表中 cratecargo 之前,所以在最终列表中它也必须在 cargo 之前。不稳定排序可能会产生这个结果,但也可能给出这个答案

cargo
crate
package
rust

也就是说,结果*可能*与原始顺序不同。

正如您所料,更少的约束通常意味着更快的速度。如果您不关心稳定性,这些不稳定排序可能比稳定排序变体更快。一如既往,最好都试试看!这些函数是通过 RFC 1884 添加的,如果您想了解更多详情,包括基准测试,可以查看该 RFC。

此外,以下 API 也已稳定

有关更多信息,请参阅详细发行说明

Cargo 特性

Cargo 在此版本中有一些不错的升级。首先,您在 crates.io 的认证令牌以前存储在 ~/.cargo/config 中。作为配置文件,它通常以 644 权限存储,即世界可读。但它包含一个秘密令牌。我们已将令牌移动到 ~/.cargo/credentials,这样它可以设置为 600 权限,并对系统上的其他用户隐藏。

如果您在 Cargo 包中使用次要二进制文件,您知道它们会放在 src/bin 中。然而,有时您可能需要多个具有复杂逻辑的次要二进制文件;在这种情况下,您会有 src/bin/client.rssrc/bin/server.rs,并且它们的任何子模块也会放在同一个目录中。这容易造成混淆。作为替代,我们现在约定俗成地支持 src/bin/client/main.rssrc/bin/server/main.rs 的结构,这样您可以将较大的二进制文件彼此更好地分开。

有关更多信息,请参阅详细发行说明

1.20.0 的贡献者

许多人共同努力创建了 Rust 1.20。没有大家的贡献,我们不可能完成。感谢!