
Rust 1.99.0 发布了。
除了版本更新,最近 Rust 生态也有一些值得关注的动向:英伟达加入了 Rust 基金会,成为白金会员,Google 也持续在 Android 中引入 Rust 代码。在我看来,这些都在释放一个信号:Rust 正变得越来越受欢迎。
如果你也想入门 Rust,现在有 AI 可以辅助学习,我觉得正是开始的好时机。已经在用 Rust 的朋友,则可以先看看这次 1.99.0 带来了哪些更新。
如果你之前通过 rustup 安装过 Rust,可以用下面的命令更新到 1.99.0:
sh
rustup update stable
下面是 1.99.0 版本的主要更新。
extern "C" 可变参数函数
从 Rust 1.99.0 开始,稳定版支持使用 "C" 和 "C-unwind" ABI 定义 C ABI 可变参数函数。这类函数通过可变参数列表(...)接收任意数量的参数。
此前,Rust 已经可以调用外部定义的可变参数函数,例如 libc::printf。从 Rust 1.99 开始,也可以直接用 Rust 编写这类函数了:
rust
/// SAFETY: must be called with (at least) 2 i32 arguments.
unsafe extern "C" fn sum(mut args: ...) -> i32 {
// SAFETY: guaranteed by the caller.
let a = unsafe { args.next_arg::<i32>() };
let b = unsafe { args.next_arg::<i32>() };
a + b
}
fn foo() -> i32 {
unsafe { sum(0i32, 2i32) }
}
这个例子只读取并相加前两个参数,调用者需要保证至少传入两个 i32。
上例中的可变参数 args 在函数体内的类型是 VaList<'_>,它在各个目标平台上都与 C 的 va_list 类型保持 ABI 兼容。VaArgSafe trait 约束了可读取的类型,但不会自动检查实际传入的参数数量和类型,因此调用者仍需保证读取操作满足安全条件。
这个版本还稳定了使用非 "C" ABI 定义裸可变参数函数的能力,这类函数必须通过内联汇编编写。
通过裸指针获取内存布局信息
这个版本明确了通过裸指针获取所指向值的大小和对齐要求时需要满足的安全条件,涵盖 Sized 和非 Sized 类型。
对于 Sized 类型,此前就可以通过 size_of::<T>() 和 align_of::<T>() 获取大小和对齐要求。本次稳定的接口也支持查询非 Sized 类型所指向值的布局信息,但调用时需要满足相应的安全条件。这些函数的签名仍带有 unsafe,调用时需要使用 unsafe 块。
本次稳定的三个函数是:
Layout::for_value_rawmem::size_of_val_rawmem::align_of_val_raw
不建议在 Box::leak 之后再释放内存
Rust 1.99 并未改变相关的语言语义,但更新了 Box::leak 的文档,不再推荐先泄漏内存、之后又将其释放的用法。
原因是,这类代码可能与当前及未来的编译器优化发生冲突。官方发布说明还提到,随着自定义分配器即将稳定,这个问题尤其突出。如果之后还需要释放内存,应优先使用 Box::into_non_null 或 Box::into_raw。
这项建议也适用于标准库中的其他 leak 函数。
本次稳定的 API
- 为
Box<[T; N]>实现IntoIterator - 为
&Box<[T; N]>实现IntoIterator - 为
&mut Box<[T; N]>实现IntoIterator VecDeque::retain_backcore::ffi::VaListBox::into_non_nullBox::from_non_nullVec::into_partsVec::from_partscore::mem::size_of_val_rawcore::mem::align_of_val_rawcore::alloc::Layout::for_value_rawString::from_utf8_lossy_ownedstring::FromUtf8Error::into_utf8_lossy- 为
StepBy<I>实现FusedIterator std::fs::set_timesstd::fs::set_times_nofollow