Rust 团队很高兴宣布 Rust 的新版本 1.40.0。Rust 是一种编程语言,它赋予每个人构建可靠高效软件的能力。
如果您之前通过 rustup 安装了 Rust 的旧版本,获取 Rust 1.40.0 非常简单,只需
$ rustup update stable
如果您还没有安装,可以从我们网站上的相应页面 获取 rustup
,并查看 GitHub 上的 1.40.0 的详细发布说明。
1.40.0 稳定版中的新内容
Rust 1.40.0 的亮点包括 #[non_exhaustive]
以及对 macros!()
和 #[attribute]
的改进。最后,借用检查迁移警告在 Rust 2015 中已成为硬错误。有关更多信息,请查看 详细的发布说明。
#[non_exhaustive]
结构体、枚举和变体
假设您是 crate alpha
的库作者,它有一个 pub struct Foo
。您希望将 alpha::Foo
的字段也设为 pub
,但您不确定是否会在将来的版本中向 Foo
添加更多字段。因此,您现在面临一个困境:要么将字段设为私有,这会带来相应的缺点,要么冒着用户依赖于确切字段的风险,当您添加一个新字段时,他们的代码就会出现问题。Rust 1.40.0 引入了一种方法来打破僵局:#[non_exhaustive]
。
当 #[non_exhaustive]
属性附加到 struct
或 enum
的变体时,它将阻止定义它的 crate 之外的代码构建该 struct
或变体。为了避免将来出现问题,其他 crate 也被禁止对字段进行穷举匹配。以下示例说明了依赖于 alpha
的 beta
中的错误
// alpha/lib.rs:
#[non_exhaustive]
struct Foo {
pub a: bool,
}
enum Bar {
#[non_exhaustive]
Variant { b: u8 }
}
fn make_foo() -> Foo { ... }
fn make_bar() -> Bar { ... }
// beta/lib.rs:
let x = Foo { a: true }; //~ ERROR
let Foo { a } = make_foo(); //~ ERROR
// `beta` will still compile when more fields are added.
let Foo { a, .. } = make_foo(); //~ OK
let x = Bar::Variant { b: 42 }; //~ ERROR
let Bar::Variant { b } = make_bar(); //~ ERROR
let Bar::Variant { b, .. } = make_bar(); //~ OK
// -- `beta` will still compile...
幕后发生的事情是,#[non_exhaustive]
struct
或 enum
变体的构造函数的可见性降低到 pub(crate)
,从而阻止了定义它的 crate 之外的访问。
#[non_exhaustive]
可能更重要的一个方面是,它也可以附加到 enum
本身。一个例子,来自标准库,是 Ordering
#[non_exhaustive]
pub enum Ordering { Relaxed, Release, Acquire, AcqRel, SeqCst }
在这种情况下,#[non_exhaustive]
的目的是确保随着时间的推移可以添加更多变体。这是通过阻止其他 crate 对 Ordering
进行穷举模式匹配来实现的。也就是说,编译器会拒绝
match ordering {
// This is an error, since if a new variant is added,
// this would suddenly break on an upgrade of the compiler.
Relaxed | Release | Acquire | AcqRel | SeqCst => {
/* logic */
}
}
相反,其他 crate 需要通过添加使用例如 _
的通配符分支来考虑更多变体的可能性
match ordering {
Relaxed | Release | Acquire | AcqRel | SeqCst => { /* ... */ }
// OK; if more variants are added, nothing will break.
_ => { /* logic */ }
}
有关 #[non_exhaustive]
属性的更多详细信息,请查看 稳定性报告。
宏和属性改进
在 1.40.0 中,我们对宏和属性进行了一些改进,包括
-
例如,您可以编写
type Foo = expand_to_type!(bar);
,其中expand_to_type
将是一个过程宏。 -
这包括
bang!()
宏,例如macro_rules! make_item { ($name:ident) => { fn $name(); } } extern { make_item!(alpha); make_item!(beta); }
现在还支持
extern { ... }
块 中项目上的过程宏属性extern "C" { // Let's assume that this expands to `fn foo();`. #[my_identity_macro] fn foo(); }
-
函数式 (
mac!()
) 和属性 (#[mac]
) 宏现在都可以生成macro_rules!
项目。有关卫生方面的详细信息,请参阅附带的稳定性报告。 -
$m:meta
匹配器 支持 任意令牌流值。也就是说,以下现在有效
macro_rules! accept_meta { ($m:meta) => {} } accept_meta!( my::path ); accept_meta!( my::path = "lit" ); accept_meta!( my::path ( a b c ) ); accept_meta!( my::path [ a b c ] ); accept_meta!( my::path { a b c } );
借用检查迁移警告在 Rust 2015 中已成为硬错误
在 1.35.0 版本中,我们宣布,NLL 在 Rust 2015 中推出,此前它是在 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!()
的更短、更令人难忘且更方便的版本。 -
通过将切片重复
n
次来创建Vec<T>
。 -
此函数从可变引用中
take
值,并将其替换为类型的默认值。这类似于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<Box<T>>
)分别生成Option<&T>
和Option<&mut T>
。 -
此函数将
Option<Option<T>>
扁平化为Option<T>
,为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。没有你们,我们无法做到。 感谢!