You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
4.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Rust 新版解读 | 1.59 | 重点: 内联汇编、解构式赋值
Rust 团队于今天凌晨( 2022-02-25 )发布了最新的 1.59 版本,其中最引人瞩目的特性应该就是支持在代码中内联汇编了,一起来看看。
## 内联汇编( inline assembly )
该特性对于需要底层控制的应用非常有用,例如想要控制底层执行、访问特定的机器指令等。
例如,如果目标平台是 `x86-64` 时,你可以这么写:
```rust
use std::arch::asm;
// 使用 shifts 和 adds 实现 x 乘以 6
let mut x: u64 = 4;
unsafe {``
asm!(
"mov {tmp}, {x}",
"shl {tmp}, 1",
"shl {x}, 2",
"add {x}, {tmp}",
x = inout(reg) x,
tmp = out(reg) _,
);
}
assert_eq!(x, 4 * 6);
```
大家发现没,这里的格式化字符串的使用方式跟我们平时的 `println!`、`format!` 并无区别, 除了 `asm!` 之外, `global_asm!` 宏也可以这么使用。
内联汇编中使用的汇编语言和指令取决于相应的机器平台截至目前Rust 支持以下平台的内联汇编:
- x86 和 x86-64
- ARM
- AArch64
- RISC-V
如果大家希望深入了解,可以看官方的 [Reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html) 文档,同时在 [Rust Exercise](https://zh.exercise.rs/unsafe/inline-asm) 中提供了更多的示例(目前正在翻译中..)。
## 解构式赋值( Destructuring assignments)
现在你可以在赋值语句的左式中使用元组、切片和结构体模式了。
```rust
let (a, b, c, d, e);
(a, b) = (1, 2);
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5, f: 3 };
assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
```
这种使用方式跟 `let` 保持了一致性,但是需要注意,使用 `+=` 的赋值语句还不支持解构式赋值。
## const 泛型
#### 为参数设置默认值
现在我们可以为 const 泛型参数设置默认值:
```rust
struct ArrayStorage<T, const N: usize = 2> {
arr: [T; N],
}
impl<T> ArrayStorage<T> {
fn new(a: T, b: T) -> ArrayStorage<T> {
ArrayStorage {
arr: [a, b],
}
}
}
```
#### 取消参数顺序的限制
在之前版本中,类型参数必须要在所有的 const 泛型参数之前,现在,这个限制被放宽了,例如你可以这样交替排列它们:
```rust
fn cartesian_product<
T, const N: usize,
U, const M: usize,
V, F
>(a: [T; N], b: [U; M], f: F) -> [[V; N]; M]
where
F: FnMut(&T, &U) -> V
{
// ...
}
```
## 减少二进制文件体积:删除 debug 信息
对于受限的环境来说,减少编译出的二进制文件体积是非常重要的。
在之前,我们可以在二进制文件创建后,手动的来完成。现在 cargo 和 rustc 支持在链接( linked )后就删除 debug 信息,在 `Cargo.toml` 中新增以下配置:
```toml
[profile.release]
strip = "debuginfo"
```
以上配置会将 `release` 二进制文件中的 debug 信息移除。你也可以使用 `"symbols"``true` 选项来移除所有支持的 `symbol` 信息。
根据 reddit 网友的测试,如果使用了 `strip = true`,那编译后的体积将大幅减少(50% 左右):
- 先使用 `lto = true` : 4,397,320 bytes
- 再使用 `strip = true` : 2,657,304 bytes
- 最后 `opt-level = "z"` : 1,857,680 bytes
如果是 WASM还可以使用以下配置进一步减少体积:
```toml
[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-Os']
```
[github上一个开源仓库](https://github.com/rsadsb/adsb_deku/blob/master/CHANGELOG.md#unreleased)也证明了这一点,总体来看,这个配置的效果是非常显著的!
## 默认关闭增量编译
1.59.0 版本默认关闭了增量编译的功能(你可以通过环境变量显式地启用:`RUSTC_FORCE_INCREMENTAL=1` ),这会降低已知 Bug [#94124](https://github.com/rust-lang/rust/issues/94124) 的影响,该 Bug 会导致增量编译过程中的反序列化错误和 `panic`
不过大家也不用担心,这个 Bug 会在 1.60.0 版本修复,也就是 6 周后,增量编译会重新设置为默认开启,如果没有意外的话 :)
## 稳定化的 API 列表
一些方法和特征实现现在已经可以 stable 中使用,具体见[官方发布说明](https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html#stabilized-apis)