Rust 新版解读 | 1.68 | crates index 优化

Rust 1.68 官方 release doc: Announcing Rust 1.68.0 | Rust Blog

通过 rustup 安装的同学可以使用以下命令升级到 1.68 版本:

$ rustup update stable

Cargo 稀疏注册协议 (sparse protocol)

Cargo的“稀疏”注册协议已经稳定,它是用来读取注册在 crates.io 上的 crates 的索引的基础设施。以前的 git 协议(目前仍然是默认协议)会克隆一个包括所有 crates 的索引的仓库,但这已经开始遇到扩展限制问题,在更新该仓库时会出现明显的延迟。新协议应在访问 crates.io 时提供显着的性能提升,因为它只会下载有关实际用到的 crates 的索引。

要使用新的协议,需要设置环境变量 CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse ,或者编辑 .cargo/config.toml 文件添加:

[registries.crates-io]
protocol = "sparse"

稀疏注册协议目前计划于 1.70.0 版本成为默认的协议。更多细节可以看官方博客的 announcementRFC 2789, 当前 Cargo Book 的 文档

局部 Pin 构造

新增的 pin! 宏能够用 T 构造一个 Pin<&mut T> ,从而匿名捕获在局部状态内。这通常叫做 堆栈固定(stack-pinning),同时这个堆栈也可以被 async fn 或者 代码块 来捕获住。这个宏和一些 crates 里提供的(比如 tokio::pin!)很像,但是标准库可以利用 Pin 的内部结构和 临时生命周期拓展(Temporary lifetime extension)来实现出更像表达式的宏。

#![allow(unused)]
fn main() {
/// Runs a future to completion.
fn block_on<F: Future>(future: F) -> F::Output {
    let waker_that_unparks_thread = todo!();
    let mut cx = Context::from_waker(&waker_that_unparks_thread);
    // Pin the future so it can be polled.
    let mut pinned_future = pin!(future);
    loop {
        match pinned_future.as_mut().poll(&mut cx) {
            Poll::Pending => thread::park(),
            Poll::Ready(result) => return result,
        }
    }
}
}

在这个例子中,原来的 future 将被移动到一个临时的局部区域,由新的 pinned_future 引用,类型为 Pin<&mut F>,并且该 pin 受制于正常的借用检查器以确保它不会超过局部作用域。

alloc 默认错误处理

当 Rust 内存分配失败时,类似于 Box::newVec::push 的 API 无法反映出这个错误,从而采取了一些不同的措施。当使用 std 时,程序会打印 stderr 然后中止。从 Rust 1.68.0 开始,包含 std 的二进制程序仍然会继续这样,而不保护 std 只包含 alloc 的二进制程序会对内存分配错误调用 panic!,如果需要可以再进一步通过 #[panic_handler] 来调整其行为。

未来,std 也可能会改成这样。

Others

其它更新细节,和稳定的API列表,参考原Blog