Rust 团队很高兴宣布 Rust 的最新版本 1.16.0。Rust 是一门专注于安全、速度和并发性的系统编程语言。
如果您已经安装了旧版本的 Rust,获取 Rust 1.16 非常简单,只需运行
如果您尚未安装,可以从我们的网站上找到合适的页面获取 rustup,并在 GitHub 上查看 1.16.0 的详细发行说明。
1.16.0 stable 版本包含什么
Rust 1.16 中最大的新增功能是 cargo check。这个新的子命令应该在许多情况下加快开发工作流程。
它有什么作用?让我们退一步,谈谈 rustc 如何编译您的代码。编译有很多“趟”(passes),也就是说,编译器从源代码到生成最终二进制文件需要许多不同的步骤。您可以通过向 nightly 编译器传递 -Z time-passes 参数来查看这些步骤(以及它们花费的时间和内存)
rustc +nightly hello.rs -Z time-passes
time: 0.003; rss: 16MB parsing
time: 0.000; rss: 16MB recursion limit
time: 0.000; rss: 16MB crate injection
time: 0.000; rss: 16MB plugin loading
time: 0.000; rss: 16MB plugin registration
time: 0.049; rss: 34MB expansion
<snip>
步骤很多。但是,您可以将这个过程视为两个大步骤:首先,rustc 执行所有安全检查,确保您的语法正确,等等。其次,一旦它确定一切就绪,它就生成最终的二进制代码,也就是您最终执行的代码。
事实证明,第二步花费大量时间。而且大多数情况下,它不是必需的。也就是说,当您在编写 Rust 代码时,许多开发人员会采用这样的工作流程
- 编写代码。
- 运行
cargo build确保其编译通过。 - 根据需要重复步骤 1-2。
- 运行
cargo test确保测试通过。 - 返回步骤 1。
在步骤二中,您实际上从未运行代码。您正在寻求编译器的反馈,而不是真正运行二进制文件。cargo check 正是支持这种情况:它运行所有编译器的检查,但不生成最终的二进制文件。
那么您实际上能获得多少加速呢?与大多数性能相关的问题一样,答案是“视情况而定”。以下是一些非常不科学的基准测试结果
| 项目 | cargo | diesel | |
|---|---|---|---|
| 首次 build | 134.75s | 236.78s | 15.27s |
| 首次 check | 50.88s | 148.52s | 12.81s |
| 提速 | 2.648 | 1.594 | 1.192 |
| 二次 build | 15.97s | 64.34s | 13.54s |
| 二次 check | 2.9s | 9.29s | 12.3s |
| 提速 | 5.506 | 6.925 | 1.100 |
“首次”(initial)类别指的是克隆项目后的第一次构建。“二次”(secondary)类别涉及在 src\lib.rs 文件顶部添加一行空行并再次运行命令。这就是为什么首次构建的提速更显著;它们还包括对所有依赖项以及 crate 本身的检查。正如您所见,依赖项多的大型项目看到了很大的改进,而小型项目的收益则较为温和。
我们也在努力整体上改进编译时间,尽管目前还没有特别需要强调的内容。
其他改进
为了支持 cargo check,rustc 学会了生成一种新类型的文件:.rmeta。这个文件只包含关于特定 crate 的元数据。cargo check 需要这些信息来检查依赖项的类型等。它也对 Rust Language Server 以及未来可能出现的更多工具非常有用。
另一个重要的变化是移除了一个长期存在的诊断提示:consider using an explicit lifetime parameter。当您有不正确的生命周期注解,并且编译器认为您可能想表达别的意思时,就会出现此诊断提示。请考虑以下代码
use FromStr;
在这里,Rust 不确定如何处理生命周期;按照代码的写法,无法保证 s 的生命周期与 Name 一样长,而 Name 的有效性需要这个条件。我们尝试使用 Rust 1.15.1 编译这段代码
|
| &) )>
| |
|
&
编译器解释了问题,并给出了一个有用的建议。那我们试试看:修改代码,加入 'a,然后再次编译
|
| &) ) )>
| |
还是不行。这个帮助信息实际上没什么帮助。它确实建议添加另一个生命周期,这次是在 Name 上。如果我们这样做...
<snip>
&)>
... 编译器啊,这不就是我们已经有的吗!
这个诊断提示是出于好意,但出错时,它的错误是非常严重的,正如您在这里看到的。有时它甚至不会建议有效的 Rust 语法!此外,更高级的 Rust 用户并不真正需要这个建议,但新的 Rustaceans 会认真对待它们,然后走上这条错误的道路。因此,我们决定目前完全删除这个帮助信息。未来我们可能会重新引入它,但前提是我们能够限制误报。
顺带一提:上述实现是不可行的;
Name需要使用String,而不是&str。
在其他诊断变化方面,之前的 Rust 版本会尝试提供有用的建议来修复拼写错误
let foo = 5;
println!;
会给出这个错误
error[E0425]: cannot find value `ffo` in this scope
--> foo.rs:4:20
|
4 | println!("{}", ffo);
| ^^^ did you mean `foo`?
然而,这只在某些情况下发生:有时在局部变量中,以及结构体字段中。现在这几乎可以在任何地方发生。当结合一些其他相关改进时,这类诊断的准确性有了显著提高。
有关更多信息,请参阅详细的发行说明。
标准库稳定化
本次发布有 21 个新的 API 得到了稳定
VecDeque::truncateVecDeque::resizeString::insert_strDuration::checked_addDuration::checked_subDuration::checked_divDuration::checked_mulstr::replacenstr::repeatSocketAddr::is_ipv4SocketAddr::is_ipv6IpAddr::is_ipv4IpAddr::is_ipv6Vec::dedup_byVec::dedup_by_keyResult::unwrap_or_default<*const T>::wrapping_offset<*mut T>::wrapping_offsetCommandExt::creation_flagsFile::set_permissionsString::split_off
此外,现有的一些函数也得到了一些小的改进。例如 writeln! 现在也有了一个单参数形式,就像 println! 一样。虽然最终只是写入一个换行符,但这是一种很好的对称性。
标准库中的所有结构体现在都实现了 Debug trait。
当对 &str 进行切片时,您会看到更好的错误提示。例如,这段代码
&"abcαβγ"
是不正确的。它会生成这个错误
thread 'str::test_slice_fail_boundary_1' panicked at 'byte index 4 is not
a char boundary; it is inside 'α' (bytes 3..5) of `abcαβγ`'
分号 ; 后面的部分是新增的。
有关更多信息,请参阅详细的发行说明。
Cargo 特性
除了 cargo check,Cargo 和 crates.io 还增加了一些新的亮点。例如,cargo build 和 cargo doc 现在支持 --all 标志,可以用一个命令构建和生成工作区中所有 crate 的文档。
Cargo 现在新增了 --version --verbose 标志,与 rustc 保持一致。
Crates.io 现在可以在您的 crate 页面上展示您的 TravisCI 或 AppVeyor 徽章。
此外,Cargo 和 crates.io 都理解类别(categories)。与自由形式的关键词(keywords)不同,类别是经过组织的。另外,关键词用于搜索,而类别不是。换句话说,类别旨在帮助浏览,而关键词旨在帮助搜索。
您可以在这里按类别浏览 crate。
有关更多信息,请参阅详细的发行说明。
1.16.0 的贡献者
上一个版本,我们推出了thanks.rust-lang.org。我们一直在进行一些幕后的重构工作,以便支持更多项目而不仅仅是 Rust 本身;我们希望在下一次发布中推出这项功能。
共有 135 位个人为 Rust 1.16 做出了贡献。感谢你们!