Rust 1.99.0 发布了,聊聊几个我觉得有意思的变化

Rust 1.99.0 发布了,聊聊几个我觉得有意思的变化

10 月 1 号发的,rustup update 一把梭就行。这次没什么惊天动地的东西,但有几个稳定化的 API 是实打实等了很久的。另外版本号到 1.99 了,下一个就是 1.100,莫名有点感慨。

Rust 终于能定义 C 可变参数函数了

以前 Rust 只能声明 C 的可变参数函数(比如 printf),自己写一个不行。现在 c_variadic 稳定了,Rust 这边可以直接定义,大概长这样:

pub unsafe extern "C" fn sum(count: usize, mut args: ...) -> i32 {
    let mut total = 0;
    for _ in 0..count {
        total += args.arg::<i32>();
    }
    total
}

配合这次一起稳定的 core::ffi::VaList 使用。平时写业务代码的人可能一辈子用不上,但写 FFI、给 C 库做 binding 的人应该等这个等了好几年。我没细测,生产用之前先去翻下文档里的 UB 约束。

Vec::into_parts / from_parts,终于不用手搓三件套了

let (ptr, len, cap) = my_vec.into_parts();
// ... 过 ffi 边界折腾一圈 ...
let v = unsafe { Vec::from_parts(ptr, len, cap) };

以前要自己 ptr::read / mem::forget / set_len 拼,写对不难,但每次写都得集中精神。现在标准库直接给了,Box 还多了 into_non_null / from_non_null。都是小补丁,但属于那种“早该如此”的。

String::from_utf8_lossy_owned

let s = String::from_utf8_lossy_owned(bytes);

跟 from_utf8_lossy 的区别是吃 Vec<u8> 所有权:如果本来就是合法 UTF-8,直接复用原来的内存,零拷贝;只有非法时才分配新的。做网络协议解析、读脏数据的地方能省一次分配,挺实在的一个优化。

std::fs::set_times,复制文件保留时间戳不用找第三方 crate 了

以前想给文件设置 atime/mtime,得去翻 filetime 这种 crate。现在标准库直接有 fs::set_times,还有 set_times_nofollow(不跟随符号链接的版本)。写备份工具、同步工具的人会很开心。

Cargo 多了个 debug profile,CI 下默认关增量编译

这次 Cargo 有两个动作,信息量其实不小。

一个是新增了内置的 debug profile,目前和 dev 完全没区别。官方明说了,这是为以后改 dev 的默认值铺路——dev 以后可能不再默认带调试信息,追求更快的编译迭代。也就是说现在先占个坑,让你提前把依赖切过去,免得到时候 breaking 来得太突然。

另一个是跑在 CI 里默认关增量编译(靠 CI 环境变量判断)。说实话这算是官方承认现实:CI 机器上增量缓存基本用不上,还拖慢编译,关了是对的。真想加速 CI 还是去配 sccache。

另外 workspace 依赖现在可以在成员里覆盖 default-features 了(要 edition 2024+):

serde = { workspace = true, default-features = false }

以前成员里写 default-features = false 会被直接忽略,还只给个 warning,monorepo 里被这个坑过的人应该不少。

升级前看一眼这几个

  • std::i32::MAX 这种写法这次彻底 deprecated 了,改成 i32::MAX。老代码里 grep 一下,五分钟的事。
  • RangeInclusive(a..=b)迭代器优化了,但副作用是:已经耗尽的 range,再调 start() / end() 或者拿去当切片索引,行为可能跟以前不一样。官方说这些行为本来就没保证过,不算 breaking,但万一你有代码依赖这个,升级后得测一下。
  • no_mangle 用在泛型上现在是 hard error 了,之前能混过去的这次直接编译失败。

其他的:LLVM 升到 23,riscv64-unknown-linux-musl 升到 Tier 2 带 host tools,rustdoc 生成文档快了 20% 到 40%(文档多的 crate 构建能省点时间)。

总的来说是个常规小版本,升级无痛,顺手把上面那几个 API 记一下,下次写代码能少折腾。完整列表去看官方 release notes 就行。