宣布 Rust 1.13

2016 年 11 月 10 日 · Rust 核心团队

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

与往常一样,您可以从我们网站上的相应页面安装 Rust 1.13.0,并在 GitHub 上查看1.13.0 的详细发行说明。此版本中包含 1448 个补丁。

Rust 经历了一个繁忙的季节。我们在短时间内举办了三个 Rust 会议,分别是RustConfRustFestRust Belt Rust。很高兴看到这么多 Rustaceans 亲自参加,有些人是第一次参加!我们一直在思考未来,制定2017 年路线图,并构建用户告诉我们他们需要的工具。

即使在所有这些事情都在进行的同时,我们也发布了一个充满有趣新玩具的新版本。

1.13 稳定版中的内容

1.13 版本包含对语言的几个扩展,包括期待已久的 ? 运算符、编译时间改进、对 Cargo 和标准库的次要功能添加。此版本还包含许多对文档和错误报告的小改进,这些改进由许多贡献者完成,但在发行说明中没有单独提及。

此版本包含对 Cargo 的重要安全更新,Cargo 依赖于 curl 和 OpenSSL,而这两个软件最近都发布了安全更新。有关更多信息,请参阅curl 7.51.0OpenSSL 1.0.2j 的相应公告。

? 运算符

Rust 获得了一个新的运算符 ?,它通过减少相关的视觉噪音,使错误处理更加愉快。它通过解决一个简单的问题来做到这一点。为了说明这一点,假设我们有一些代码要从文件中读取一些数据

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("username.txt");

    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

这段代码有两个可能失败的路径,一个是打开文件,另一个是从文件中读取数据。如果这两个操作中的任何一个无法正常工作,我们希望从 read_username_from_file 返回一个错误。这样做需要对 I/O 操作的结果进行 match。但是,在这种简单的用例中,我们只是将错误向上传播到调用堆栈,匹配只是模板代码——看到它以相同的模式重复出现,并没有为读者提供太多有用的信息。

使用 ?,上面的代码看起来像这样

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("username.txt")?;
    let mut s = String::new();

    f.read_to_string(&mut s)?;

    Ok(s)
}

? 是我们之前编写的整个匹配语句的简写。换句话说,? 应用于 Result 值,如果它是 Ok,它会解包它并提供内部值。如果它是 Err,它会从您当前所在的函数中返回。从视觉上看,它更加直观。我们不再使用整个匹配语句,而是使用单个 "?" 字符来表示我们在这里以标准方式处理错误,即通过将它们向上传播到调用堆栈。

经验丰富的 Rustaceans 可能认识到,这与自 Rust 1.0 以来一直可用的 try! 宏相同。事实上,它们是相同的。在 1.13 之前,read_username_from_file 可以这样实现

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = try!(File::open("username.txt"));
    let mut s = String::new();

    try!(f.read_to_string(&mut s));

    Ok(s)
}

那么,当我们已经有一个宏时,为什么要扩展语言呢?原因有很多。首先,try! 已经被证明非常有用,并且在惯用的 Rust 中经常使用。它被使用得如此频繁,以至于我们认为它值得拥有一个简洁的语法。这种演变是强大的宏系统的一大优势:可以对语言语法的推测性扩展进行原型设计和迭代,而无需修改语言本身,反过来,事实证明特别有用的宏可以表明缺少的语言特性。从 try!? 的演变就是一个很好的例子。

try! 需要一个更简洁的语法的原因之一是,当连续使用 try! 的多次调用时,它看起来非常不美观。考虑一下

try!(try!(try!(foo()).bar()).baz())

foo()?.bar()?.baz()?

相比。第一个在视觉上很难扫描,并且每一层错误处理都会在表达式前面添加一个额外的 try! 调用。这会过度关注微不足道的错误传播,掩盖了主要代码路径,在本例中是 foobarbaz 的调用。这种带有错误处理的链式方法调用发生在构建器模式等情况下。

最后,专用语法将在未来更容易生成专门针对 ? 的更友好的错误消息,而通常很难为宏扩展的代码生成友好的错误消息(不过,在此版本中,? 错误消息可以改进)。

虽然这是一个小功能,但根据我们迄今为止的经验,? 感觉是对旧的 try! 宏的可靠的人体工程学改进。这是一个很好的例子,说明了 Rust 将继续接收到的增量式、生活质量改进,它将打磨我们已经强大的基础语言的粗糙角落。

RFC 243 中阅读有关 ? 的更多信息。

性能改进

最近,编译器性能得到了很多关注。此版本带来了好消息,并且还有更多改进即将到来。

Mark Simulacrum 和 Nick Cameron 一直在改进perf.rust-lang.org,这是我们用于跟踪编译器性能的工具。它定期在专用硬件上运行rustc-benchmarks 套件,并跟踪结果随时间的变化。此工具记录了编译器中每个阶段的结果,并被编译器开发人员用来缩小性能回归的提交范围。它是我们工具箱中的重要组成部分!

我们可以使用此工具查看图表,该图表显示了 1.13 开发周期中的性能,如下所示。此周期涵盖了 8 月 16 日至 9 月 29 日的日期(图表从 8 月 25 日开始,并以几种方式进行过滤,以消除虚假、不完整或令人困惑的结果)。似乎有一些很大的减少,这些减少在相应的统计页面上进行了量化。



Performance graph



图表中显示的 9 月 1 日的大幅改进来自 Niko 对在翻译期间缓存规范化投影的优化。也就是说,在生成 LLVM IR 期间,编译器不再每次需要时都重新计算关联类型的具体实例,而是重用之前计算的值。此优化不会影响所有代码库,但在表现出某些模式的代码库中,例如futures-rs,其中调试模式构建时间提高了 40%,您会注意到差异。

另一个这样的优化来自 Michael Woerister,它不会影响每个板条箱,但会对某些板条箱产生重大影响,它提高了导出许多内联函数的板条箱的编译时间。当一个函数被标记为 #[inline] 时,除了为当前板条箱使用而翻译该函数之外,编译器还会将它的 MIR 表示存储在板条箱 rlib 中,并在调用它的每个板条箱中将该函数翻译为 LLVM IR。Michael 做的优化事后看来很明显:在某些情况下,内联函数仅供其他板条箱使用,而从未从定义它们的板条箱中调用;因此,编译器不需要在定义它们的板条箱中翻译内联函数的代码,除非它们被直接调用。这节省了 rustc 将函数转换为 LLVM IR 以及 LLVM 优化和将函数转换为机器代码的成本。

在某些情况下,这会导致显着的改进。ndarray 板条箱的构建时间提高了 50%,而在(未发布的)winapi 0.3 板条箱中,rustc 现在根本不生成任何机器代码。

但是,还有更多!Nick Nethercote 也将注意力转向了编译器性能,专注于分析和微优化。此版本包含他工作的几个成果,并且还有更多成果将在 1.14 中发布。

其他值得注意的更改

此版本包含对 Cargo 的重要安全更新,Cargo 依赖于 curl 和 OpenSSL,而这两个软件最近都发布了安全更新。有关更多信息,请参阅curl 7.51.0OpenSSL 1.0.2j 的相应公告。

宏现在可以在类型位置使用(RFC 873),并且属性可以应用于语句(RFC 16)。

// Use a macro to name a type
macro_rules! Tuple {
    { $A:ty,$B:ty } => { ($A, $B) }
}

let x: Tuple!(i32, i32) = (1, 2);
// Apply a lint attribute to a single statement
#[allow(non_snake_case)]
let BAD_STYLE = List::new();

内联 drop 标志已被删除。以前,在条件移动的情况下,编译器会在结构体中内联存储一个“drop 标志”(增加其大小)以跟踪它是否需要被 drop。这意味着某些结构体占用了一些意外的额外空间,这会干扰将带有析构函数的类型通过 FFI 传递。对于没有条件移动的代码来说,这也是一种空间浪费。在 1.12 中,MIR 成为默认值,这为许多改进奠定了基础,包括删除这些内联 drop 标志。现在,drop 标志存储在需要它们的函数的堆栈帧上的额外槽中。

1.13 包含一个针对使用硬件浮点数的 ARM 目标的代码生成中的严重错误(大多数 ARM 目标都是如此)。Rust 中的 ARM 目标目前处于我们的第二级支持层,因此此错误被确定为不会阻止发布。由于 1.13 包含安全更新,因此必须针对 ARM 的用户建议使用 1.14 测试版,该测试版将很快修复 ARM 的问题。

语言稳定化

库稳定化

Cargo 功能

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

1.13.0 的贡献者

共有 155 位个人为 1.13.0 做出了贡献。非常感谢你们!

  • Aaron Gallagher
  • Abhishek Kumar
  • aclarry
  • Adam Medziński
  • 艾哈迈德·查尔斯
  • 阿列克谢·克拉多夫
  • 亚历山大·冯·格鲁克四世
  • 亚历山大·奥利维拉
  • 亚历克斯·布尔卡
  • 亚历克斯·克里奇顿
  • 阿马纽·丹特拉斯
  • 阿米特·莱维
  • 安德烈亚·科拉迪
  • 安德烈·博古斯
  • 安德鲁·坎恩
  • 安德鲁·坎蒂诺
  • 安德鲁·利金
  • 安德鲁·帕塞尔蒂纳
  • 安迪·拉塞尔
  • 阿里埃尔·本·耶胡达
  • arthurprs
  • 阿什利·威廉姆斯
  • athulappadan
  • 奥斯汀·希克斯
  • bors
  • 布莱恩·安德森
  • c4rlo
  • 凯勒布·琼斯
  • CensoredUsername
  • cgswords
  • changchun.fan
  • 许秋香
  • 克里斯·斯坦库斯
  • 克里斯托弗·塞尔
  • 克里斯·王
  • clementmiao
  • Cobrand
  • 科里·法威尔
  • 克里斯蒂·科布扎伦科
  • crypto-universe
  • dangcheng
  • 丹尼尔·巴拉奇
  • DarkEld3r
  • 大卫·托尔奈
  • 达斯汀·本辛
  • 爱德华·布尔特斯库
  • 爱德华-米哈伊·布尔特斯库
  • 埃坦·阿德勒
  • 埃里克·乌格尔达尔
  • 埃斯特班·库伯
  • 尤金·布尔金
  • 尤金·R·冈萨雷斯
  • 法比安·扎伊瑟
  • 费德里科·拉瓦西奥
  • 菲利克斯·S·克洛克二世
  • 弗洛里安·吉尔彻
  • 加文·贝克
  • 格奥尔格·布兰德尔
  • ggomez
  • 詹尼·奇卡雷利
  • 纪尧姆·戈麦斯
  • 雅各布
  • jacobpadkins
  • 杰克·戈德斯伯勒
  • 杰克·古尔丁
  • 雅各布·德姆勒
  • 詹姆斯·杜利
  • 詹姆斯·米勒
  • 贾里德·罗伊施
  • 贾里德·怀尔斯
  • 杰弗里·塞弗里德
  • JessRudder
  • 乔·尼曼
  • 约翰内斯·洛特贝格
  • 约翰·菲尔鲍
  • johnthagen
  • 乔纳斯·希夫温克
  • 乔纳森·特纳
  • 豪尔赫·阿帕里西奥
  • 约瑟夫·邓恩
  • 乔希·特里普莱特
  • 贾斯汀·勒菲布尔
  • 基根·麦克阿利斯特
  • 凯斯·杨
  • 李俊洪
  • king6cong
  • 骑士
  • knight42
  • 凯洛·金斯伯格
  • Liigo
  • 马尼什·戈雷加奥卡
  • 马克-西穆拉库姆
  • 马修·皮齐亚克
  • 马特·伊克斯塔特
  • mcarton
  • 迈克尔·莱恩
  • 迈克尔·沃里斯特
  • 米哈伊尔·莫丁
  • 莫希特·阿加瓦尔
  • 纳齐姆·坎·阿尔蒂诺瓦
  • 尼尔·威廉姆斯
  • 尼古拉斯·内瑟科特
  • 尼克·卡梅伦
  • 尼克·普拉特
  • 尼尔斯·萨沙·里迪克
  • 尼基塔·巴克萨利亚尔
  • 尼科·马特萨基斯
  • 奥利弗·米德尔顿
  • 奥利弗·施耐德
  • orbea
  • 帕纳谢·M·芬迪拉
  • 帕特里克·沃尔顿
  • 保罗·法内利
  • philipp
  • 菲尔·拉夫温德
  • 皮奥特·雅夫尼亚克
  • pliniker
  • QuietMisdreavus
  • 拉胡尔·夏尔马
  • 理查德·雅尼斯·戈德施密特
  • 斯科特·A·卡尔
  • 斯科特·奥尔森
  • 肖恩·麦克阿瑟
  • 塞巴斯蒂安·乌尔里希
  • 塞巴斯蒂安·玛丽
  • 徐尚贤
  • 塞尔吉奥·贝尼特斯
  • 夏亚姆·桑达尔·B
  • silenuss
  • 西蒙纳斯·卡兹劳斯卡斯
  • 西蒙·萨平
  • 斯里尼瓦斯·雷迪·塔蒂帕蒂
  • 斯特凡·施林德勒
  • 斯特凡·休格尔
  • 史蒂夫·克拉布尼克
  • 史蒂文·艾伦
  • 史蒂文·法克勒
  • 特里·孙
  • 托马斯·加西亚
  • 蒂姆·诺伊曼
  • 托比亚斯·布赫
  • 托马斯·米阿斯科
  • trixnz
  • 特谢潘·莱孔霍贝
  • 乌尔里希·魏甘德
  • 乌尔里克·斯维德鲁普
  • 瓦迪姆·丘古诺夫
  • 瓦迪姆·佩特罗琴科夫
  • 万雅·科西奇
  • 文森特·埃舍
  • 韦斯利·怀瑟
  • 威廉·李
  • 罗希敏
  • 约西·康斯坦蒂诺夫斯基
  • zjhmale