2016 年的 Rust

2015 年 8 月 14 日 · Nicholas Matsakis 和 Aaron Turon

本周标志着 Rust 1.0 发布三个月。随着我们开始进入 1.0 后的步伐,我们想谈谈 **1.0 的意义回顾,以及我们对 Rust 在未来一年的展望**。

1.0 的意义

Rust 1.0 专注于稳定性、社区和清晰度。

  • **稳定性**,我们在之前的文章中讨论了很多,介绍了我们的发布渠道和稳定化流程。

  • **社区**一直是 Rust 最大的优势之一。但在 1.0 发布的前一年,我们引入了并完善了 RFC 流程,最终形成了子团队来管理每个特定领域的 RFC。社区范围内的 RFC 辩论对于交付高质量的 1.0 版本至关重要。

  • 所有这些在 1.0 之前进行的完善都是为了达到对 Rust 代表的 **清晰度**

总而言之,**Rust 令人兴奋,因为它赋予了力量:你可以无惧地进行黑客攻击**。你可以在以前可能没有尝试过的环境中做到这一点,从 Ruby 或 Python 等语言中降级,首次涉足系统编程。

这就是 Rust 1.0;但接下来会发生什么?

未来方向

经过核心团队、早期生产用户和更广泛社区的广泛讨论,我们确定了在未来一年左右的时间里想要进行的一些改进,这些改进可以分为三类

  • 加倍投入基础设施;
  • 专注于关键功能的差距;
  • 扩展到 Rust 的新应用领域。

让我们看看每个类别中的一些最大计划。

加倍投入:基础设施投资

Crater

我们对 Rust 的基本稳定性承诺是,版本之间的升级是“无忧无虑的”。为了实现这一承诺,我们需要检测导致代码停止工作的编译器错误。当然,编译器本身有一个大型测试套件,但这只是“野外”存在的代码的一小部分。**Crater 是一种旨在弥合这一差距的工具,它通过测试编译器与 crates.io 中找到的所有包,让我们更好地了解是否有任何代码在最新的 nightly 版本上停止编译。**

Crater 迅速成为必不可少的工具。我们定期将 nightly 版本与最新的稳定版本进行比较,并使用 crater 检查正在进行的分支并估计更改的影响。

有趣的是,我们经常发现,当代码停止编译时,并不是因为编译器中的错误。而是因为我们修复了一个错误,而该代码恰好依赖于旧的行为。即使在这些情况下,使用 crater 也有助于我们改善体验,因为它建议我们应该通过警告来逐步进行修复。

在未来一年左右的时间里,我们计划以多种方式改进 crater

  • 将覆盖范围扩展到 Linux 以外的其他平台,并在覆盖的库上运行测试套件。
  • 使其更易于使用:留下 @crater: test 注释以尝试 PR。
  • 生成库作者可以使用该工具的版本,以查看其更改对下游代码的影响。
  • 包含来自 crates.io 以外的其他来源的代码。

增量编译

Rust 一直采用“crate 范围”的编译模型。这意味着 Rust 编译器会一次性读取 crate 中的所有源文件。这些文件将被类型检查,然后交给 LLVM 进行优化。这种方法非常适合进行深度优化,因为它让 LLVM 可以完全访问整个代码集,从而实现更好的内联、更精确的分析等等。但是,这可能意味着周转时间很慢:即使你只编辑一个函数,我们也会重新编译所有内容。当项目变得很大时,这会成为负担。

增量编译项目旨在通过让 Rust 编译器保存中间副产品并重复使用它们来改变这一点。这样,当你调试问题或调整代码路径时,**你只需要重新编译你更改过的内容,这应该会使“编辑-编译-测试”循环快得多**。

该项目的一部分是重构编译器以引入新的中间表示,我们称之为 MIR。MIR 是一种更简单、更低级的 Rust 代码形式,它将更复杂的功能简化为更简单的形式,从而使编译器的其余部分更简单。这是对非词法生命周期(下一节讨论)等语言更改的关键推动因素。

IDE 集成

一流的 IDE 支持可以帮助使 Rust 更加高效。到目前为止,像 RacerVisual RustRust DT 这样的先锋项目一直在很大程度上没有编译器支持。**我们计划扩展编译器以允许与 IDE 和其他工具进行更深层的集成**;计划是最初专注于两个 IDE,然后从那里扩展。

专注于:弥合关键功能的差距

特化

零成本抽象的概念分解为两个独立的目标,正如 Stroustrup 所指出的

  • 你不使用的东西,你就不会为它付费。
  • 你使用的东西,你无法手工编写得更好。

Rust 1.0 在语言特性和标准库方面基本上已经实现了第一个目标。但它并没有完全实现第二个目标。例如,考虑以下特征

pub trait Extend<A> {
    fn extend<T>(&mut self, iterable: T) where T: IntoIterator<Item=A>;
}

Extend 特征为将来自任何类型迭代器的数据插入集合提供了很好的抽象。但对于当今的特征来说,这也意味着每个集合只能提供一个适用于所有迭代器类型的实现,这需要实际重复调用 .next()。在某些情况下,你可以手工编写得更好,例如,只需调用 memcpy

为了弥合这一差距,我们提出了 **特化,允许你提供多个重叠的特征实现,只要一个实现明显比另一个更具体**。除了为 Rust 提供更完整的工具集来实现零成本抽象之外,特化还改善了其代码重用故事。有关更多详细信息,请参阅 RFC

借用检查器改进

借用检查器在某种程度上是 Rust 的核心;它是编译器中让我们在没有垃圾回收的情况下实现内存安全的部分,它通过捕获使用后释放错误等来实现。但偶尔,借用检查器也会“捕获”非错误,例如以下模式

match map.find(&key) {
    Some(...) => { ... }
    None => {
        map.insert(key, new_value);
    }
}

像上面的代码片段这样的代码是完全可以的,但借用检查器今天难以处理它,因为 map 变量被借用了整个 match 的主体,阻止它被 insert 修改。我们计划通过重构借用检查器来解决这一缺陷,使其能够以更细粒度的(“非词法”)区域来查看代码——这得益于上面提到的迁移到 MIR。

插件

今天在 Rust 中你可以做一些非常酷的事情——如果你愿意使用 Nightly 频道。例如,regex crate 带有宏,这些宏在编译时将正则表达式直接转换为机器代码以匹配它们。或者以 rust-postgres-macros crate 为例,它在编译时检查字符串的 SQL 语法有效性。像这样的 crate 利用了高度不稳定的编译器插件系统,该系统目前暴露了太多编译器内部机制。**我们计划提出一个新的插件设计,该设计更加健壮,并提供对卫生宏扩展的内置支持。**

扩展到:将 Rust 带到新的地方

交叉编译

虽然今天可以使用 Rust 进行交叉编译,但这涉及大量手动配置。**我们的目标是实现一键式交叉编译。**我们的想法是,为另一个目标编译 Rust 代码应该很简单

  1. 下载目标的预编译 libstd 版本,如果你还没有的话。
  2. 执行 cargo build --target=foo
  3. 没有步骤 3。

Cargo install

Cargo 和 crates.io 是一个非常棒的用于分发库的工具,但它缺乏任何安装可执行文件的方法。 RFC 1200 描述了对 cargo 的一个简单补充,即 cargo install 命令。与传统的 make install 类似,**cargo install 将在你的路径中放置一个可执行文件,以便你可以运行它。** 这可以作为一种简单的分发渠道,对于编写针对 Rust 开发人员的工具的人来说尤其有用(他们可能熟悉运行 cargo)。

跟踪钩子

使用 Rust 最有前景的方式之一是将 Rust 代码“嵌入”到用更高级语言(如 Ruby 或 Python)编写的系统中。这种嵌入通常是通过为 Rust 代码提供 C API 来完成的,当目标系统使用“C 友好”的内存管理方案(如引用计数或保守式 GC)时,这种方法效果很好。

与使用更高级 GC 的环境集成可能非常具有挑战性。也许最突出的例子是 JavaScript 引擎,如 V8(由 node.js 使用)和 SpiderMonkey(由 FirefoxServo 使用)。与这些引擎集成需要非常仔细的编码,以确保所有对象都被正确地根植;小的错误很容易导致崩溃。这些正是 Rust 旨在消除的内存管理问题。

为了将 Rust 带到具有高级 GC 的环境中,我们计划扩展编译器,使其能够生成“跟踪钩子”。这些钩子可以被 GC 用于扫描堆栈并识别根,从而使编写与高级 VM 无缝且轻松集成的代码成为可能。当然,设计将尊重 Rust 的“按需付费”原则,因此不与 GC 集成的代码不受影响。

结语:RustCamp 2015 和 Rust 社区在 2016 年

我们最近举办了首届 Rust 大会,RustCamp 2015,该大会吸引了 160 名参会者,门票全部售罄。看到如此多的 Rust 社区成员亲临现场,并看到我们在线空间的氛围转化为一个友好且易于接近的线下活动,真是令人惊叹。大会第一天以 Nicholas Matsakis 和 Aaron Turon 的主题演讲开场,他们阐述了核心团队对我们身处何处以及我们前进方向的看法。幻灯片已在线发布(以及其他一些演讲),以上内容作为缺失的配乐。更新:现在您也可以看到演讲了!

那天有一个明确的主题:Rust 最大的潜力是解锁新一代系统程序员。这不仅仅是因为语言本身;更重要的是,因为社区文化倡导“不知道堆栈和堆之间的区别?别担心,Rust 是学习它的好方法,我很乐意向你展示如何做。”

我们上面概述的技术工作对我们 2016 年的愿景很重要,但我们审核和社区团队的工作以及所有不懈地——热情地——欢迎来自各种背景的人加入 Rust 社区的人的工作同样重要。因此,我们对 Rust 未来一年的最大愿望是,随着其社区的壮大,它将继续保持其现有的欢迎精神。