translation(appendix/rust-versions) : 1.66

pull/1135/head
EluvK 2 years ago
parent 602b4dc820
commit 9bdf4cf582

@ -345,3 +345,4 @@
- [1.63](appendix/rust-versions/1.63.md)
- [1.64](appendix/rust-versions/1.64.md)
- [1.65](appendix/rust-versions/1.65.md)
- [1.66](appendix/rust-versions/1.66.md)

@ -0,0 +1,112 @@
# Rust 新版解读 | 1.66 | 重点: 有字段枚举的显示判别
> Rust 1.66 官方 release doc: [Announcing Rust 1.66.0 | Rust Blog](https://blog.rust-lang.org/2022/12/15/Rust-1.66.0.html)
通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.66 版本:
```shell
$ rustup update stable
```
## 对有字段枚举的显示判别
枚举的显示判别在跨语言传递值时很关键,需要两个语言里每个枚举值的判别是一致的,比如:
```rust
#[repr(u8)]
enum Bar {
A,
B,
C = 42,
D,
}
```
这个例子里,枚举 `Bar` 使用了 `u8` 作为原语表型,并且 `Bar::C` 使用 42 来判别,其它没有显示判别的枚举值会按照源码里地顺序自动地递增赋值,这里的 `Bar::A` 是0`Bar::B` 是1`Bar::D` 是43。如果没有显示判别那就只能在 `Bar::B``Bar::C` 之间加上 40 个无意义的枚举值了。
在1.66之前,枚举的显示判别只能用在无字段枚举上。现在对有字段枚举的显示判别也稳定了:
```rust
#[repr(u8)]
enum Foo {
A(u8),
B(i8),
C(bool) = 42,
}
```
注意:可以通过 `as` 转换(比如 `Bar::C as u8` )来判断一个无字段枚举的判别值,但是 Rust 还没有给有字段枚举提供语言层面上的获取原始判别值的方法,只能通过 unsafe 的代码来检查有字段枚举的判别值。考虑到这个使用场景往往出现在必须使用 unsafe 代码的跨语言的 FFI 里,希望这没有造成太大的负担。如果你的确需要的话,参考 `std::mem::discriminant`
## 黑盒方法 `core::hint::black_box`
当对编译器产生的代码做基准测试时,常常需要阻止一些优化,比如下面的代码里, `push_cap` 在一个循环里执行了4次 `Vec::push`
```rust
fn push_cap(v: &mut Vec<i32>) {
for i in 0..4 {
v.push(i);
}
}
pub fn bench_push() -> Duration {
let mut v = Vec::with_capacity(4);
let now = Instant::now();
push_cap(&mut v);
now.elapsed()
}
```
如果你检查一下在 x86_64 机器上编译的优化输出结果,你会注意到整个 `push_cap` 方法都被优化掉了...
```text
example::bench_push:
sub rsp, 24
call qword ptr [rip + std::time::Instant::now@GOTPCREL]
lea rdi, [rsp + 8]
mov qword ptr [rsp + 8], rax
mov dword ptr [rsp + 16], edx
call qword ptr [rip + std::time::Instant::elapsed@GOTPCREL]
add rsp, 24
ret
```
现在可以通过调用 `black_box` 来避免类似情况的发送。 虽然实际上 `black_box` 内部只会取走值并直接返回,但是编译器会认为这个方法可能做任何事情。
``` rust
use std::hint::black_box;
fn push_cap(v: &mut Vec<i32>) {
for i in 0..4 {
v.push(i);
black_box(v.as_ptr());
}
}
```
这样就可以得到展开循环的[结果](https://rust.godbolt.org/z/Ws1GGbY6Y)
```text
mov dword ptr [rbx], 0
mov qword ptr [rsp + 8], rbx
mov dword ptr [rbx + 4], 1
mov qword ptr [rsp + 8], rbx
mov dword ptr [rbx + 8], 2
mov qword ptr [rsp + 8], rbx
mov dword ptr [rbx + 12], 3
mov qword ptr [rsp + 8], rbx
```
你还能发现结果里有 `black_box` 带来的副作用,无意义的 `mov qword ptr [rsp + 8], rbx` 指令在每一次循环后出现,用来获取 `v.as_ptr()` 作为参数传递给并未真正使用的方法。
注意到上面的例子里,`push` 指令都不用考虑内存分配的问题,这是因为编译器运行在 `Vec::with_capacity(4)` 的条件下。你可以尝试改动一下 `black_box` 的位置或者在多处使用,来看看其对编译的优化输出的影响。
## `cargo remove`
1.62里我们引入了 `cargo add` 来通过命令行给你的项目增加依赖项。现在可以使用 `cargo remove` 来移除依赖了。
## Others
其它更新细节和稳定的API列表参考[原Blog](https://blog.rust-lang.org/2022/12/15/Rust-1.66.0.html#stabilized-apis)
Loading…
Cancel
Save