Rust 新版解读 | 1.59 | 重点: 内联汇编、解构式赋值

Rust 团队于今天凌晨( 2022-02-25 )发布了最新的 1.59 版本,其中最引人瞩目的特性应该就是支持在代码中内联汇编了,一起来看看。

内联汇编( inline assembly )

该特性对于需要底层控制的应用非常有用,例如想要控制底层执行、访问特定的机器指令等。

例如,如果目标平台是 x86-64 时,你可以这么写:

#![allow(unused)]
fn main() {
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 文档,同时在 Rust Exercise 中提供了更多的示例(目前正在翻译中..)。

解构式赋值( Destructuring assignments)

现在你可以在赋值语句的左式中使用元组、切片和结构体模式了。

#![allow(unused)]
fn main() {
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 泛型参数设置默认值:

#![allow(unused)]
fn main() {
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 泛型参数之前,现在,这个限制被放宽了,例如你可以这样交替排列它们:

#![allow(unused)]
fn main() {
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 中新增以下配置:

[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,还可以使用以下配置进一步减少体积:

[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-Os']

github 上一个开源仓库也证明了这一点,总体来看,这个配置的效果是非常显著的!

默认关闭增量编译

1.59.0 版本默认关闭了增量编译的功能(你可以通过环境变量显式地启用:RUSTC_FORCE_INCREMENTAL=1 ),这会降低已知 Bug #94124 的影响,该 Bug 会导致增量编译过程中的反序列化错误和 panic

不过大家也不用担心,这个 Bug 会在 1.60.0 版本修复,也就是 6 周后,增量编译会重新设置为默认开启,如果没有意外的话 :)

稳定化的 API 列表

一些方法和特征实现现在已经可以 stable 中使用,具体见官方发布说明