Rust 团队很高兴地宣布 Rust 的新版本 1.34.0。Rust 是一种编程语言,它使每个人都能够构建可靠且高效的软件。
如果您之前通过 rustup 安装了 Rust 版本,那么获取 Rust 1.34.0 就如同运行以下命令一样简单:
$ rustup update stable
如果您还没有安装 rustup,您可以从我们网站上的相应页面获取 rustup
。
1.34.0 稳定版的新特性
此版本中最大的特性是引入了备用 cargo
注册表。该版本还包括对文档测试中 ?
的支持、对 #[attribute(..)]
的一些改进以及 TryFrom
的稳定化。请继续阅读以了解一些亮点,或查看详细的发行说明以获取更多信息。
cargo
注册表
备用 自 1.0 之前,Rust 就拥有一个公共 crate 注册表,crates.io。人们使用 cargo publish
发布 crate,并且很容易将这些 crate 包含在 Cargo.toml
的 [dependencies]
部分中。
但是,并非每个人都希望将其 crate 发布到 crates.io。维护专有/闭源代码的人员不能使用 crates.io,而是被迫使用 git
或 path
依赖项。这对于小型项目来说通常可以接受,但是如果大型组织内有大量闭源 crate,那么您将失去 crates.io 拥有的版本控制支持的优势。
在此版本中,Cargo 获得了对备用注册表的支持。这些注册表与 crates.io 共存,因此您可以编写依赖于来自 crates.io 和自定义注册表的 crate 的软件。但是,crates.io 上的 crate 不能依赖于外部注册表。
要使用备用注册表,您必须将以下行添加到您的 .cargo/config
。此文件可以位于您的主目录 (~/.cargo/config
) 或相对于包目录。
[registries]
my-registry = { index = "https://my-intranet:8080/git/index" }
依赖备用注册表中的 crate 很简单。在您的 Cargo.toml
中指定依赖项时,使用 registry
键来告诉 Cargo 您希望从备用注册表获取 crate
[dependencies]
other-crate = { version = "1.0", registry = "my-registry" }
作为 crate 作者,如果您希望将 crate 发布到备用注册表,则首先需要使用 cargo login
命令将身份验证令牌保存到 ~/.cargo/credentials
中
cargo login --registry=my-registry
然后,您可以使用 --registry
标志来指示发布时要使用哪个注册表
cargo publish --registry=my-registry
关于如何运行自己的注册表,请参阅文档。
?
文档测试中的 RFC 1937 提出在 fn main()
、#[test]
函数和 doctest 中添加对使用 ?
运算符的支持,允许它们返回 Option<T>
或 Result<T, E>
,其中错误值在 fn main()
的情况下导致非零退出代码,在测试的情况下导致测试失败。
对 fn main()
和 #[test]
的支持在很多版本之前就已经实现。但是,对文档测试中的支持仅限于具有显式 fn main()
的 doctest。
在此版本中,已添加对 doctest 中 ?
的完全支持。现在,您可以在文档测试中编写如下代码:
/// ```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)]
。过程宏 crate 将使用字符串来指定此类语法,例如 #[range("0..10")]
在此 Rust 版本中,自定义属性 #[attr($tokens)]
现在接受 $tokens
中的任意标记流,使它们与宏相提并论。如果您是过程宏 crate 的作者,请检查您的自定义属性的语法中是否有不必要的字符串,以及是否可以使用标记流更好地表达它们。
TryFrom
和 TryInto
TryFrom
和 TryInto
trait 已被稳定化,以允许可失败的类型转换。
例如,整数类型上的 from_be_bytes
和相关方法采用数组,但数据通常通过切片读取。手动在切片和数组之间进行转换很繁琐。使用新 trait,可以使用 .try_into()
内联完成。
let num = u32::from_be_bytes(slice.try_into()?);
对于不会失败的转换(例如 u8
到 u32
),添加了 Infallible
类型。这也允许为所有现有的 From
实现提供 TryFrom
的通用实现。在将来,我们希望将 Infallible
转换为 !
(never) 类型的别名。
fn before_exec
已弃用,改为使用 unsafe fn pre_exec
在类 Unix 系统上,函数 CommandExt::before_exec
允许您在调用 exec
之前安排一个闭包运行。
提供的闭包将在 fork 之后在子进程的上下文中运行。这意味着诸如文件描述符和内存映射区域之类的资源可能会被复制。换句话说,您现在可以将非 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_fn
和 iter::successors
已稳定。前者允许您从 FnMut() -> Option<T>
构造迭代器。要迭代地从向量中弹出元素,您现在可以编写 from_fn(|| vec.pop())
。同时,后者创建一个新的迭代器,其中每个连续项都基于前一项计算得出。
此外,以下 API 已稳定:
- Any::type_id
- Error::type_id
- slice::sort_by_cached_key
- str::escape_debug
- str::escape_default
- str::escape_unicode
- str::split_ascii_whitespace
- Instant::checked_add
- Instant::checked_sub
- SystemTime::checked_add
- SystemTime::checked_sub
有关更多详细信息,请参阅详细的发行说明。