Rust 团队很高兴宣布 Rust 的新版本 1.35.0。Rust 是一种编程语言,它使每个人都能构建可靠高效的软件。
如果您之前通过 rustup 安装了 Rust,获取 Rust 1.35.0 就像
$ rustup update stable
如果您还没有,您可以从我们网站上的相应页面获取 rustup
,并查看 GitHub 上1.35.0 的详细发布说明。
1.35.0 稳定版中的内容
此版本的亮点是为 Box<dyn FnOnce>
、Box<dyn FnMut>
和 Box<dyn Fn>
分别实现了 FnOnce
、FnMut
和 Fn
闭包特征。此外,闭包现在可以强制转换为不安全的函数指针。在Rust 1.32.0 中引入的 dbg!
宏现在也可以在没有参数的情况下调用。此外,标准库还进行了许多稳定化。继续阅读以了解一些亮点,或查看详细的发布说明以获取更多信息。
Box<dyn Fn*>
实现 Fn*
闭包特征
为 在 Rust 1.35.0 中,FnOnce
、FnMut
和 Fn
特征现在分别为 Box<dyn FnOnce>
、Box<dyn FnMut>
和 Box<dyn Fn>
实现。
以前,如果您想调用存储在已装箱闭包中的函数,您必须使用FnBox
。这是因为 Box<dyn FnOnce>
及其同类实例没有实现相应的 Fn*
特征。这也意味着无法将已装箱函数传递给期望 Fn
特征实现者的代码,并且您必须创建临时闭包才能将它们传递下去。
这最终是由于编译器在推理此类实现方面的局限性,该局限性已随着未定大小局部变量的引入而得到解决。
通过此版本,您现在可以在期望实现函数特征的项目的地方使用已装箱函数。
以下代码现在可以工作
fn foo(x: Box<dyn Fn(u8) -> u8>) -> Vec<u8> {
vec![1, 2, 3, 4].into_iter().map(x).collect()
}
此外,您现在可以直接调用 Box<dyn FnOnce>
对象
fn foo(x: Box<dyn FnOnce()>) {
x()
}
unsafe fn
指针
将闭包强制转换为 自Rust 1.19.0 以来,可以将不从其环境中捕获的闭包强制转换为函数指针。例如,您可以编写
fn twice(x: u8, f: fn(u8) -> u8) -> u8 {
f(f(x))
}
fn main() {
assert_eq!(42, twice(0, |x| x + 21));
}
但是,这尚未扩展到 unsafe
函数指针。通过此版本的 Rust,您现在可以这样做。例如
/// The safety invariants are those of the `unsafe fn` pointer passed.
unsafe fn call_unsafe_fn_ptr(f: unsafe fn()) {
f()
}
fn main() {
// SAFETY: There are no invariants.
// The closure is statically prevented from doing unsafe things.
unsafe {
call_unsafe_fn_ptr(|| {
dbg!();
});
}
}
dbg!()
在没有参数的情况下调用 为了所有偶尔和频繁的“打印调试器”的利益,Rust 1.32.0 看到了dbg!
宏的发布。回顾一下,该宏允许您快速检查某些表达式的值及其上下文。例如,在运行
fn main() {
let mut x = 0;
if dbg!(x == 1) {
x += 1;
}
dbg!(x);
}
...您将看到
[src/main.rs:4] x == 1 = false
[src/main.rs:8] x = 0
如上一节中调用高阶函数 call_unsafe_fn_ptr
所示,您现在也可以在不传递任何参数的情况下调用 dbg!
。这在跟踪应用程序所采取的分支时很有用。例如,使用
fn main() {
let condition = true;
if condition {
dbg!();
}
}
...您将看到
[src/main.rs:5]
库稳定化
在 1.35.0 中,许多 API 已经稳定。
此外,还添加了一些实现,并进行了其他更改。有关更多详细信息,请查看详细的发布说明。
将浮点数的符号复制到另一个数上
通过此版本,新的方法 copysign
已添加到浮点基本类型f32
和f64
中
顾名思义,您可以使用它们将一个数字的符号复制到另一个数字上。例如
fn main() {
assert_eq!(3.5_f32.copysign(-0.42), -3.5);
}
Range
是否包含
某个值
检查 Rust 1.35.0 包含 Range
类型上的一些新方法
Range::contains
RangeFrom::contains
RangeTo::contains
RangeInclusive::contains
RangeToInclusive::contains
通过这些,您可以轻松地检查给定值是否存在于某个范围内。例如,您可以编写
fn main() {
if (0..=10).contains(&5) {
println!("Five is included in zero to ten.");
}
}
RefCell
值映射并拆分为两个
将借用的 使用 Rust 1.35.0,您现在可以将借用的 RefCell
值映射并拆分为借用数据的多个组件的多个借用
RefCell
的值
通过闭包替换 此版本在 RefCell
上引入了便利方法 replace_with
有了它,您可以更符合人体工程学地映射和替换单元格的当前值,并将旧值作为结果返回。
按地址而不是值对指针或引用进行哈希
在此版本中,我们引入了
此函数接受一个原始指针并对其进行哈希。使用 ptr::hash
,您可以避免对引用的指向值进行哈希,而是对地址进行哈希。
Option<&T>
的内容
复制 从 Rust 1.0.0 开始,Option<&T>
和 Option<&mut T>
的方法 Option::cloned
允许您在 Some(_)
的情况下克隆内容。但是,克隆有时可能是一个昂贵的操作,并且方法 opt.cloned()
没有提供任何提示。
通过此版本的 Rust,我们引入了
Option::copied
适用于Option<&T>
和Option<&mut T>
opt.copied()
的功能与 opt.cloned()
相同。但是,调用该方法需要 T: Copy
。使用此方法,您可以确保代码在 T
不再实现 Copy
时停止编译。
Clippy 中的更改
在此版本的 Rust 中,Clippy(一个用于捕获常见错误并改进 Rust 代码的 lint 集合)添加了一个新的 lint drop_bounds
。当您向泛型函数添加边界 T: Drop
时,此 lint 会触发。例如
fn foo<T: Drop>(x: T) {}
拥有边界 T: Drop
几乎总是错误的,因为它排除了诸如 u8
之类的类型,这些类型具有微不足道的 drop-glues。此外,T: Drop
不会考虑诸如 String
之类的类型,这些类型没有直接的有趣析构函数行为,而是由于嵌入诸如 Vec<u8>
之类的类型而导致的,这些类型确实具有有趣行为。
除了drop_bounds
之外,此版本的 Clippy 拆分了 lint redundant_closure
为 redundant_closure
和 redundant_closure_for_method_calls
。
有关更多详细信息,请查看Clippy 的详细发布说明。
Cargo 中的更改
有关更多详细信息,请查看Cargo 的详细发布说明。
1.35.0 的贡献者
许多人共同创建了 Rust 1.35.0。没有你们,我们不可能做到。 谢谢!