Rust 2016

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

本周是 Rust 1.0 发布三个月纪念日。随着我们开始进入 1.0 之后的稳定发展阶段,我们想讨论一下 回顾 1.0 版本意味着什么,以及我们认为 Rust 在未来一年将走向何方

1.0 版本的重点

Rust 1.0 重点关注了稳定性、社区和清晰度。

总而言之,Rust 令人兴奋之处在于它赋予了你能力:你可以无所畏惧地编写代码。你可以在以前可能不敢尝试的环境中这样做,比如从 Ruby 或 Python 等语言转而尝试系统编程,迈出你的第一步。

这就是 Rust 1.0;那么接下来是什么?

何去何从

经过核心团队、早期生产用户和更广泛社区的深入讨论,我们确定了在未来一年左右的时间里希望实现的一系列改进,这些改进分为三个类别

  • 加倍投入基础设施;
  • 聚焦关键功能空白;
  • 拓展 Rust 的新应用领域。

让我们来看看每个类别中的一些主要计划。

加倍投入:基础设施投资

Crater

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

Crater 很快成为一个不可或缺的工具。我们定期将 nightly 版本与最新的稳定构建进行比较,并使用 crater 检查正在进行的开发分支并评估变更的影响。

有趣的是,我们经常发现当代码无法编译时,并不是因为编译器本身的 bug。相反,是因为我们*修复*了一个 bug,而该代码碰巧依赖于旧的行为。即使在这些情况下,使用 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 在语言特性和标准库方面基本上实现了第一个目标。但它还未能完全实现第二个目标。以下面这个 trait 为例

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

`Extend` trait 为将任何类型的迭代器中的数据插入集合提供了一个很好的抽象。但目前的 trait 意味着每个集合只能提供一个适用于*所有*迭代器类型的实现,这需要实际重复调用 `.next()`。在某些情况下,你可以手动编写出更好的代码,例如只调用 `memcpy`。

为了弥补这一差距,我们提出了**特化(specialization),它允许你提供多个相互重叠的 trait 实现,只要其中一个明显比另一个更具体**。除了为 Rust 提供一套更完整的零成本抽象工具外,特化还改善了其代码复用能力。详情请参阅该 RFC

借用检查器改进

从某种意义上说,借用检查器是 Rust 跳动的心脏;它是编译器中让我们无需垃圾回收即可实现内存安全的部分,通过捕获 use-after-free 等错误。但有时,借用检查器也会“捕获”一些非错误的代码,例如以下模式

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

上面代码片段中的代码是完全正确的,但目前的借用检查器对此感到困难,因为 `map` 变量在整个 `match` 主体中都被借用了,阻止了它被 `insert` 修改。我们计划很快通过重构借用检查器来解决这一缺点,使其能够以更细粒度(“非词法”)的区域来查看代码——这是通过转向上面提到的 MIR 实现的。

插件

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

拓展:将 Rust 带到新的领域

交叉编译

虽然现在使用 Rust 可以进行交叉编译,但这需要大量手动配置。**我们的目标是实现一键交叉编译**。

  1. 下载目标平台预编译的 libstd,如果你还没有的话。
  2. 执行 cargo build --target=foo
  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 友好”的内存管理方案(如引用计数或保守式垃圾回收)时,效果相当不错。

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

**为了将 Rust 带入使用高级垃圾回收的环境,我们计划扩展编译器,使其具备生成“跟踪钩子”的能力**。这些钩子可供垃圾回收器用于扫描堆栈并识别根对象,从而可以轻松流畅地编写与高级虚拟机集成的代码。当然,设计会遵循 Rust 的“用即付费”策略,因此不与垃圾回收器集成的代码将不受影响。

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

我们最近举办了首届 Rust 大会,RustCamp 2015,160 张门票全部售罄。亲眼见到如此多的 Rust 社区成员令人惊叹,也很高兴看到我们在线空间的氛围转化为一个友好、平易近人的线下活动。大会以 Nicholas Matsakis 和 Aaron Turon 的主题演讲拉开帷幕,他们阐述了核心团队对我们现状和未来方向的看法。幻灯片已在线提供(以及其他几个演讲),上文内容可视为缺失的“音轨”。**更新**:现在你也可以观看演讲视频了!

那一天有一个明确的主题:Rust 最大的潜力在于它能开启新一代系统程序员的大门。这不仅仅是因为语言本身;同样重要的是社区文化,它传递着这样的信息:“不知道栈和堆的区别?别担心,Rust 是学习它们的绝佳方式,我非常乐意教你。”

我们在上面概述的技术工作对于我们 2016 年的愿景很重要,但我们的版主和社区团队的工作同样重要,还有所有不懈地——热情地——欢迎各种背景的人们加入 Rust 社区的人们。因此,我们对 Rust 未来一年最大的愿望是,随着社区的发展,它能够继续保持今天这种欢迎的精神。