宣布 Rust 1.34.0

2019 年 4 月 11 日 · Rust 发布团队

Rust 团队很高兴宣布 Rust 的新版本 1.34.0。Rust 是一种编程语言,它赋予每个人构建可靠高效软件的能力。

如果您之前通过 rustup 安装了 Rust,获取 Rust 1.34.0 就像

$ rustup update stable

如果您还没有,您可以从我们网站上的相应页面 获取 rustup

1.34.0 稳定版中的内容

此版本中最大的功能是引入了替代 cargo 注册表。该版本还包括对文档测试中 ? 的支持,对 #[attribute(..)] 的一些改进,以及 TryFrom 的稳定化。继续阅读以了解一些亮点,或查看 详细的发布说明 以获取更多信息。

替代 cargo 注册表

从 1.0 之前开始,Rust 就有一个公共的板条箱注册表,crates.io。人们使用 cargo publish 发布板条箱,并且很容易在 Cargo.toml[dependencies] 部分中包含这些板条箱。

但是,并非每个人都希望将他们的板条箱发布到 crates.io。维护专有/闭源代码的人无法使用 crates.io,而是被迫使用 gitpath 依赖项。这对于小型项目通常是可以的,但是如果您在一个大型组织中有很多闭源板条箱,您将失去 crates.io 提供的版本控制支持的优势。

通过此版本,Cargo 获得了对替代注册表的支持。这些注册表与 crates.io 共存,因此您可以编写依赖于来自 crates.io 和自定义注册表的板条箱的软件。但是,crates.io 上的板条箱不能依赖于外部注册表。

要使用替代注册表,您必须将这些行添加到您的 .cargo/config 中。此文件可以在您的主目录 (~/.cargo/config) 中,也可以相对于包目录。

[registries]
my-registry = { index = "https://my-intranet:8080/git/index" }

依赖于来自替代注册表的板条箱很容易。在 Cargo.toml 中指定依赖项时,使用 registry 键让 Cargo 知道您希望从替代注册表中获取板条箱

[dependencies]
other-crate = { version = "1.0", registry = "my-registry" }

作为板条箱作者,如果您希望将您的板条箱发布到替代注册表,您首先需要使用 cargo login 命令将身份验证令牌保存到 ~/.cargo/credentials

cargo login --registry=my-registry

然后,您可以使用 --registry 标志来指示在发布时使用哪个注册表

cargo publish --registry=my-registry

有关于如何运行您自己的注册表的 文档

文档测试中的 ?

RFC 1937 提出在 fn main()#[test] 函数和 doctests 中添加对使用 ? 运算符的支持,允许它们返回 Option<T>Result<T, E>,错误值在 fn main() 的情况下导致非零退出代码,在测试的情况下导致测试失败。

fn main()#[test] 中的支持是在 很多版本之前 实现的。但是,文档测试中的支持仅限于具有显式 fn main() 的 doctests。

在此版本中,已添加对 doctests 中 ? 的完全支持。现在,您可以在您的文档测试中编写以下内容

/// ```rust
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok::<(), io::Error>(())
/// ```
fn my_func() {}

您仍然必须在文档测试的底部指定正在使用的错误类型。

自定义属性接受任意标记流

过程宏 在 Rust 中可以定义它们消耗的自定义属性。到目前为止,此类属性仅限于根据特定语法作为路径和文字的树,例如

#[foo(bar)]
#[foo = "bar"]
#[foo = 0]
#[foo(bar = true)]
#[foo(bar, baz(quux, foo = "bar"))]

与过程宏不同,这些辅助属性不能接受分隔符中的任意标记流,因此您不能编写 #[range(0..10)]#[bound(T: MyTrait)]。过程宏板条箱将改为使用字符串来指定此类语法,例如 #[range("0..10")]

通过此 Rust 版本,自定义属性 #[attr($tokens)] 现在接受 $tokens 中的任意标记流,使其与宏相当。如果您是过程宏板条箱的作者,请检查您的自定义属性是否在其语法中包含不必要的字符串,以及它们是否可以使用标记流更好地表达。

TryFromTryInto

TryFromTryInto 特性已稳定,以允许错误类型转换。

例如,整数类型上的 from_be_bytes 和相关方法接受数组,但数据通常通过切片读取。在切片和数组之间进行转换手动操作很繁琐。使用新的特性,可以使用 .try_into() 内联完成。

let num = u32::from_be_bytes(slice.try_into()?);

对于不会失败的转换,例如 u8u32,添加了 Infallible 类型。这也允许对所有现有的 From 实现进行 TryFrom 的通用实现。将来,我们希望将 Infallible 转换为 ! (永不) 类型 的别名。

fn before_exec 已弃用,取而代之的是 unsafe fn pre_exec

在类 Unix 系统上,函数 CommandExt::before_exec 允许您安排在调用 exec 之前运行的闭包。

提供的闭包将在分叉后在子进程的上下文中运行。这意味着资源(如文件描述符和内存映射区域)可能会被复制。换句话说,您现在可以将非 Copy 类型的值的副本复制到不同的进程中,同时保留父进程中的原始副本。这使得 有可能 导致未定义的行为并破坏 假设不复制的库

因此,函数 before_exec 应该被标记为 unsafe。在此版本的 Rust 中,我们已弃用 fn before_exec,取而代之的是 unsafe fn pre_exec。在调用 CommandExt::pre_exec 时,您有责任确保闭包不会通过对这些副本的无效使用来违反库不变式。如果您提供的库与 before_exec 处于类似情况,请考虑弃用并提供 unsafe 替代方案。

库稳定化

在 1.34.0 中,稳定的原子整数类型的集合已扩展,现在提供从 8 (AtomicU8) 到 64 位的有符号和无符号变体。

以前,非零无符号整数类型,例如 NonZeroU8,已稳定。这使 Option<NonZeroU8> 的大小与 u8 相同。通过此 Rust 版本,有符号版本,例如 NonZeroI8,已稳定。

函数 iter::from_fniter::successors 已稳定。前者允许您从 FnMut() -> Option<T> 构造迭代器。要从向量中迭代地弹出元素,您现在可以编写 from_fn(|| vec.pop())。同时,后者创建一个新的迭代器,其中每个后续项都是根据前一个项计算的。

此外,这些 API 已稳定

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