Rust 团队很高兴发布 Rust 的新版本 1.40.0。Rust 是一门赋能所有人构建可靠且高效软件的编程语言。
如果你之前通过 rustup 安装过 Rust,获取 Rust 1.40.0 就像这样简单:
$ rustup update stable
如果你还没有安装,可以从我们网站的相应页面获取 rustup,并在 GitHub 上查看 1.40.0 的详细发布说明。
1.40.0 stable 版本有哪些内容
Rust 1.40.0 的亮点包括 #[non_exhaustive] 以及对 macros!() 和 #[attribute] 的改进。最后,Rust 2015 版本中的借用检查迁移警告已成为硬错误。有关更多信息,请参阅详细发布说明。
#[non_exhaustive] structs、enums 和 variants
假设你是一个名为 alpha 的 crate 的库作者,其中有一个 pub struct Foo。你希望将 alpha::Foo 的字段也设为 pub,但你不确定将来是否会为 Foo 添加更多字段。所以你现在面临一个两难境地:要么将字段设为私有,带来一系列缺点;要么冒着用户依赖确切字段的风险,当你添加新字段时可能会破坏他们的代码。Rust 1.40.0 引入了一种打破僵局的方法:#[non_exhaustive]。
属性 #[non_exhaustive] 附加到 struct 或 enum 的 variant 上时,将阻止在该 crate 外部的代码构造该 struct 或 variant。为了避免将来出现破坏性更改,其他 crate 也无法对字段进行穷尽匹配。以下示例说明了依赖于 alpha 的 beta 中的错误
// alpha/lib.rs:
// beta/lib.rs:
let x = Foo ; //~ ERROR
let Foo = make_foo; //~ ERROR
// `beta` will still compile when more fields are added.
let Foo = make_foo; //~ OK
let x = Variant ; //~ ERROR
let Variant = make_bar; //~ ERROR
let Variant = make_bar; //~ OK
// -- `beta` will still compile...
幕后发生的事情是,#[non_exhaustive] struct 或 enum variant 的构造函数的可见性降低到 pub(crate),从而阻止了在定义它的 crate 外部的访问。
#[non_exhaustive] 更重要的一个方面可能是它可以附加到 enum 本身。一个取自标准库的例子是 Ordering
在此上下文中,#[non_exhaustive] 的目的是确保随着时间的推移可以添加更多 variant。这是通过阻止其他 crate 对 Ordering 进行穷尽模式 match 来实现的。也就是说,编译器会拒绝
match ordering
相反,其他 crate 需要通过添加通配符分支(例如使用 _)来考虑更多 variant 的可能性
match ordering
有关 #[non_exhaustive] 属性的更多详细信息,请参阅稳定化报告。
宏和属性改进
在 1.40.0 中,我们引入了对宏和属性的几项改进,包括
-
例如,你可以编写
type Foo = expand_to_type!(bar);,其中expand_to_type是一个过程宏。 -
这包括感叹号宏 (
bang!()),例如extern现在也支持
extern { ... }块中项上的过程宏属性extern "C" -
函数式宏 (
mac!()) 和属性宏 (#[mac]) 现在都可以生成macro_rules!项。有关 hygiene 的详细信息,请参阅随附的稳定化报告。 -
$m:meta匹配器支持任意 token-stream 值。也就是说,以下语法现在是有效的
accept_meta!; accept_meta!; accept_meta!; accept_meta!; accept_meta!;
Rust 2015 版本中,借用检查迁移警告成为硬错误
在 1.35.0 版本中,我们宣布 NLL 已来到 Rust 2015 版本,此前 NLL 已在 Rust 1.31 版本中针对 2018 版本发布。
正如我们当时指出的,旧的借用检查器存在一些可能导致内存不安全性的错误,而 NLL 借用检查器修复了这些错误。由于这些修复会破坏一些稳定代码,我们决定逐步引入错误,通过检查旧的借用检查器是否接受该程序而 NLL 检查器是否拒绝它来判断。在这些情况下,错误会被降级为警告。
上一个版本 Rust 1.39.0 将使用 2018 版本的代码中的这些警告变更为错误。Rust 1.40.0 对使用 2015 版本的用户应用了相同的更改,彻底关闭了这些健全性漏洞。这也使我们能够清理编译器中的旧代码。
如果你的构建因为此更改而中断,或者你想了解更多信息,请查阅Niko Matsakis 的博客文章。
标准库中更多的 const fn
随着 Rust 1.40.0 的发布,以下函数成为了 const fn
标准库新增内容
在 Rust 1.40.0 中,以下函数和宏已稳定化
-
一个宏,它是
unimplemented!()的更短、更易记且更方便的版本。 -
通过重复 slice
n次来创建一个Vec。 -
此函数从可变引用中取出值,并将其替换为该类型的默认值。这类似于
Option::take和Cell::take,并为mem::replace(&mut dst, Default::default())提供了一个方便的简写形式。 -
BTreeMap::get_key_value和HashMap::get_key_value返回与提供的键对应的键值对。
-
Option::as_deref,Option::as_deref_mut这些函数的工作方式类似于
Option::as_ref和Option::as_mut,但也分别使用了Deref和DerefMut,因此opt_box.as_deref()和opt_box.as_deref_mut()(其中opt_box: Option) 分别生成> Option<&T>和Option<&mut T>。 -
此函数将
Option扁平化为Option,对于Some(Some(x))生成Some(x),否则生成None。该函数类似于Iterator::flatten。 -
返回此套接字连接到的远程对等的套接字地址。
-
{f32,f64}::to_be_bytes,{f32,f64}::to_le_bytes,{f32,f64}::to_ne_bytes,{f32,f64}::from_be_bytes,{f32,f64}::from_le_bytes, 和{f32,f64}::from_ne_bytes以大端序(网络序)、小端序和本地端字节序返回浮点数的内存表示形式,作为字节数组。
其他变化
Rust 1.40.0 版本还有其他变化:查看 Rust、Cargo 和 Clippy 中有什么变化。
另请参阅兼容性说明,检查你是否受到这些变化的影响。
1.40.0 的贡献者
许多人齐心协力创建了 Rust 1.40.0。没有你们,我们做不到。感谢大家!