Rust 1.9 发布

2016 年 5 月 26 日 · Rust 核心团队

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

一如既往,您可以从我们网站上的相应页面安装 Rust 1.9,并在 GitHub 上查看 1.9 的详细发布说明。本次发布共合并了大约 1000 个补丁。

1.9 stable 版本包含哪些内容

栈展开控制

Rust 1.9 中最大的变化是 std::panic 模块的稳定,该模块包含了停止由 panic 启动的 unwinding 过程的方法

use std::panic;

let result = panic::catch_unwind(|| {
    println!("hello!");
});
assert!(result.is_ok());

let result = panic::catch_unwind(|| {
    panic!("oh no!");
});
assert!(result.is_err());

这个新的 API 在 RFC 1236 中定义。

一般来说,Rust 区分操作失败的两种方式

  • 由于一个 *预期的问题*,例如文件未找到。
  • 由于一个 *意外的问题*,例如数组索引越界。

预期的问题通常源于你无法控制的条件;健壮的代码应该为环境可能带来的任何情况做好准备。在 Rust 中,预期的问题通过 Result 类型处理,它允许函数将问题信息返回给调用者,然后调用者可以以细粒度的方式处理错误。

意外的问题是 *bug*:它们是由于违反契约或断言而产生的。由于它们是意外的,因此以细粒度的方式处理它们没有意义。相反,Rust 采用“快速失败”(fail fast)的方法,通过 *panicking* 来实现,默认情况下,它会展开(unwind)发现错误的线程的堆栈(运行析构函数但不运行其他代码)。其他线程继续运行,但任何时候尝试与 panic 的线程通信时(无论是通过 channels 还是 shared memory),都会发现 panic。因此,Panics 会中止执行,直到某个“隔离边界”(isolation boundary),边界另一侧的代码仍然能够运行,并且可能以某种非常粗粒度的方式从 panic 中“恢复”。例如,一个服务器不一定仅仅因为其中一个线程的断言失败而宕机。

新的 catch_unwind API 提供了一种在 *线程内部* 引入新的隔离边界的方式。有几个关键的动机示例

  • 将 Rust 嵌入其他语言
  • 管理线程的抽象

对于第一种情况,跨越语言边界的 unwinding 是未定义行为,在实践中常常导致 segfaults。允许捕获 panics 意味着你可以通过 C API 安全地暴露 Rust 代码,并将 unwinding 转换为 C 端的错误。

对于第二种情况,考虑一个线程池库。如果池中的一个线程 panic,你通常不希望终止该线程本身,而是捕获 panic 并将其传达给线程池的客户端。catch_unwind API 与 resume_unwind 配对使用,后者可以用来在线程池的客户端(即其所属之处)重新启动 panicking 过程。

在这两种情况下,你都在线程内部引入了一个新的隔离边界,然后将 panic 转换为其他形式的错误并传递到别处。

最后一点:为什么是 catch_unwind 而不是 catch_panic?我们正在添加另一种 panic 策略:中止整个进程(可能在运行一个通用的 hook 后)。对于某些应用来说,这是处理程序员错误最合理的方式,并且避免 unwinding 可以带来性能和代码大小上的优势。

弃用警告

我们为库作者引入了一个新的属性:#[deprecated]。这个属性允许你标记一个 API 为弃用,当用户使用该 API 时,他们会收到弃用警告,并被指引到替代 API。弃用警告长期以来一直是标准库的一部分,但得益于 RFC 1270,它们现在可以在整个生态系统中使用。

新的目标

我们现在为几个新的目标发布标准库二进制文件

  • mips-unknown-linux-musl,
  • mipsel-unknown-linux-musl,以及
  • i586-pc-windows-msvc.

前两个目标从交叉编译的角度来看尤其有趣;详情请参阅最近关于 rustup 的博文

编译时间改进

在类型统一(type unification)期间比较变量等效性的时间复杂度从 O(n!) 降低到 O(n)。因此,一些编程模式的编译速度大大加快。

推广使用 Specialization

本次发布看到 specialization 在标准库中的首次应用。Specialization 目前仅在 nightly 版本中可用,它允许泛型代码根据更具体的类型信息自动进行 specialization。

标准库中出现这种情况的一个例子:从字符串切片 (&str) 到拥有的 String 的转换。方法 to_string 来自一个泛型 API,以前相对较慢,而自定义的 to_owned 实现提供了更好的性能。使用 specialization 后,这两个函数现在等效了

有了 specialization 的这个简单测试经验,我们将在未来版本中带来更多的性能改进。

库功能稳定

大约 80 个库函数和方法在 1.9 中稳定下来。最主要的稳定是前面描述的 std::panic 模块,但还有更多内容:

网络

  • TcpStreamTcpListenerUdpSocket 增加了一些用于配置连接的方法。
  • SocketAddr 及其变体增加了方便的 set_ip()set_port() 方法。

集合

  • BTreeSetHashSet 增加了 take()replace()get() 方法,这使得恢复原始 key 的所有权成为可能。
  • OsString 增加了一些方法,使其与 String 更接近功能对等。
  • Slices 增加了 copy_from_slice(),这是一个安全的 memcpy 形式。

编码

  • char 增加了解码为 UTF-16 的能力。

指针

  • 原始指针增加了 as_ref()as_mut() 方法,它们返回一个 Option<&T>,将 null 指针转换为 None
  • ptr::{read,write}_volatile() 允许从原始指针进行 volatile 读写。

最后,libcore 中的许多类型没有包含 Debug 实现。这在 1.9 版本中得到了修复

查看详细发布说明获取更多信息。

Cargo 特性

Cargo 有两个主要变化

首先,Cargo 现在可以并行运行

其次,增加了一个新的 flag,RUSTFLAGS这个 flag 允许你通过环境变量指定任意 flag 传递给 rustc,这对于打包者(packagers)等非常有用。

查看详细发布说明获取更多信息。

1.9 的贡献者

共有 127 位贡献者为 1.9 做出了贡献。非常感谢你们!

  • Aaron Turon
  • Abhishek Chanda
  • Adolfo Ochagavía
  • Aidan Hobson Sayers
  • Alan Somers
  • Alejandro Wainzinger
  • Aleksey Kladov
  • Alex Burka
  • Alex Crichton
  • Amanieu d'Antras
  • Andrea Canciani
  • Andreas Linz
  • Andrew Cantino
  • Andrew Horton
  • Andrew Paseltiner
  • Andrey Cherkashin
  • Angus Lees
  • Ariel Ben-Yehuda
  • Benjamin Herr
  • Björn Steinbrink
  • Brian Anderson
  • Brian Bowman
  • Christian Wesselhoeft
  • Christopher Serr
  • Corey Farwell
  • Craig M. Brandenburg
  • Cyryl Płotnicki-Chudyk
  • Daniel J Rollins
  • Dave Huseby
  • David AO Lozano
  • David Henningsson
  • Devon Hollowood
  • Dirk Gadsden
  • Doug Goldstein
  • Eduard Burtescu
  • Eduard-Mihai Burtescu
  • Eli Friedman
  • Emanuel Czirai
  • Erick Tryzelaar
  • Evan
  • Felix S. Klock II
  • Florian Berger
  • Geoff Catlin
  • Guillaume Gomez
  • Gökhan Karabulut
  • JP Sugarbroad
  • James Miller
  • Jeffrey Seyfried
  • John Talling
  • Jonas Schievink
  • Jonathan S
  • Jorge Aparicio
  • Joshua Holmer
  • Kai Noda
  • Kamal Marhubi
  • Katze
  • Kevin Brothaler
  • Kevin Butler
  • Manish Goregaokar
  • Markus Westerlind
  • Marvin Löbel
  • Masood Malekghassemi
  • Matt Brubeck
  • Michael Huynh
  • Michael Neumann
  • Michael Woerister
  • Ms2ger
  • NODA, Kai
  • Nathan Kleyn
  • Nick Cameron
  • Niko Matsakis
  • Noah
  • Novotnik, Petr
  • Oliver Middleton
  • Oliver Schneider
  • Philipp Oppermann
  • Piotr Czarnecki
  • Pyfisch
  • Richo Healey
  • Ruud van Asseldonk
  • Scott Olson
  • Sean McArthur
  • Sebastian Wicki
  • Seo Sanghyeon
  • Simon Sapin
  • Simonas Kazlauskas
  • Steve Klabnik
  • Steven Allen
  • Steven Fackler
  • Stu Black
  • Sébastien Marie
  • Tang Chenglong
  • Ted Horst
  • Ticki
  • Tim Montague
  • Tim Neumann
  • Timon Van Overveldt
  • Tobias Bucher
  • Tobias Müller
  • Todd Lucas
  • Tom Tromey
  • Tshepang Lekhonkhobe
  • Ulrik Sverdrup
  • Vadim Petrochenkov
  • Valentin Lorentz
  • Varun Vats
  • Wang Xuerui
  • Wangshan Lu
  • York Xiang
  • arcnmx
  • ashleysommer
  • bors
  • ggomez
  • gohyda
  • ituxbag
  • mitaa
  • nicholasf
  • petevine
  • pierzchalski
  • pravic
  • srinivasreddy
  • tiehuis
  • ubsan
  • vagrant
  • vegai
  • vlastachu
  • Валерий Лашманов