< 返回版块

Mike Tang 发表于 2026-11-06 20:49

Josh Triplett 盘点 Rust 未来特性

《Rust features in the future》是 LWN 对 Josh Triplett 在 Kangrejos 2026 演讲的报道。Kangrejos 是面向 Linux 内核 Rust 开发者的会议。作者 JoshTriplett 2026 年 10 月 23 日把文章转到 r/rust,采集时 155 分、54 条评论。文章作者是 LWN 的 daroc。Triplett 一开始说明这些特性完成度不一样,现在介入还有机会影响设计,也欢迎说明哪些特性会解决内核里的实际问题。

View types 让函数签名声明自己会访问结构体的哪些字段,从而只借用这一部分。函数体内部,借用检查器可以发现可变引用只用到部分字段,这时其他字段仍可以不可变借用。拆成多个函数之后,检查器不能跨函数按字段分析。语法还没定,当前工作在类型系统上。Miguel Ojeda 说内核大概会用到,之前没有单独提需求,因为已经在路线图上。Andreas Hindborg 问时间。Jana Dönszelmann 说目前只有一个人在做,正在争取资金做成全职,估计明年能看到原型。目标页在 https://goals.rust-lang.org/2026/view-types-experiment.html 。

Pattern types 在类型上再加一层模式,用来编码不变式,可以看成 NonZero 和 NonNull 的推广。示例是 type Errno = u32 is 0..4096;,布局和 ABI 仍按 u32。nightly 已有实现,还没进标准库。它不能单独做出指针对齐 niche:现在没有“总是能被某对齐值整除”这种模式。u32 实现了 Add,不表示 u32 is 0..1_000_000_000 也实现 Add。从普通整数转回 pattern type 要显式检查,并处理失败。跟踪 issue 是 https://github.com/rust-lang/rust/issues/123646 。

Linear types 和 unforgettable types 还在设想阶段。两者都要做出不能被隐式 drop 的类型。unforgettable types 还禁止用 std::mem::forget() 泄漏容纳它们的内存,用来表示必须提交或中止的数据库事务。栈上有这种类型时 panic 是 unsafe,所以语言需要保证一段代码不会 panic。这件事曾经卡在 trait solver,新 trait solver 的工作已经重新推进。Ojeda 同意这对内核有用。

Into::into() 目前不能用 turbofish 指定目标类型。turbofish 只能填函数或方法自己的类型参数,into() 的类型参数在 Into trait 上。标准库有一个只改库的修法,库团队希望放进下一个 edition。Gary Guo 问过 type ascription 等替代方案,Triplett 说试过,没有这个修法直接。

中缀模式匹配运算符 is 对应 RFC 3573。现在写成 while let Some(x) = func().await && x.some_condition() 时,要在条件和模式之间来回看。提案写成 while func().await is Some(x) && x.some_condition()。它可以用在任何期待布尔值的位置,编译器不会把它简单改写成现在的 if let。绑定作用域是能确定结果为 true 的地方。解析不向后兼容,需要未来 edition。matches!() 会保留。Triplett 说学习者可以少记一批 .is_none() 这类辅助方法。r/rust 评论里,tanoshikuidomouyo(167 分)反对在已有 if let 之外再加一套语法。JoJoJet-(92 分)写,let 把绑定放在左边,读代码时位置固定。ShantyShark(36 分)写,两套功能相同的语法应该替换旧语法,不要并存。

Polonius 是按控制流跟踪借用的借用检查器。非词法生命周期之后,仍有人能看出来合法、检查器却拒绝的程序,循环中途 return 之后下一轮是否还持有引用就是一类。Polonius 处理这类情况。nightly 已经打开。稳定前主要是去掉几处性能回退。内核同时用 stable 和 nightly 测试,Ojeda 说应该能在 Polonius 上编译。最低支持的 Rust 版本提高之前,不能对全部内核代码无条件打开,因为旧编译器里的版本还有后来修好的 bug。

编译期专用函数参照 Zig 的 comptime。现有 const fn 也能在运行时运行,所以不能调用只在编译期存在的编译器 API。只能在编译期运行的函数可以接编译期反射 API。过程宏现在要单独 crate。Triplett 说,编译期专用函数的原型就绪之后,才能正式讨论把宏写在使用点旁边。

保证尾调用用来写解释器和部分递归算法,难点是和自动析构的交互。目标页在 https://goals.rust-lang.org/2026/tail-call-loop-match.html 。演讲最后点了名字、没有展开的还有:标记函数不会 panic、#[const_continue]、完整 const generics。

原文链接:https://lwn.net/SubscriberLink/1099606/20707a62817cdd16/

const 会把 include_bytes 内联多份

这篇笔记记录 Rust 里 const 在每个使用点内联,include_bytes! 因此可能被嵌进二进制多份。作者 TanixLu 2026 年 10 月 23 日发到 r/rust,采集时 38 分、18 条评论。

示例把文件放进 pub const DATA: &'static [u8] = include_bytes!("data.bin");,hash_bytes 用 DefaultHasher 对字节切片做 Hash。main 读取 output.bin,哈希和 data_hash() 不一致就 std::fs::write(OUTPUT_PATH, static_data::DATA)。DATA 的类型是 'static 引用。作者原先以为内容只会嵌进二进制一次。后来改了无关代码,输出体积突然变小。查下来,改之前 DATA 被嵌了两份。

作者引用的说明是:常量会在每个使用点内联,包括外部 crate 的常量和非 Copy 类型。对同一常量的引用不保证指向同一地址。要保证只有一份,改成 static。

复现需要把 codegen-units 设成大于 1,例如 2。rustc 默认可能合并较小的代码生成单元。lto = "fat" 也会把重复数据优化掉。

评论里 ToTheBatmobileGuy(87 分)写,const 是编译期算完后把字节贴进每个使用点,static 是内存里一个槽。编译器有时会合并重复副本。合并不属于语言保证。

原文链接:https://www.reddit.com/r/rust/comments/1xdr3d0/the_day_const_betrayed_me/

mzstd:纯 Rust 的 zstd

mzstd 是纯 Rust 的 Zstandard 压缩库,API 对齐同一作者之前的 mbrotli。作者 Mnwamnowich 2026 年 10 月 23 日发到 r/rust,采集时 17 分、17 条评论。crate 名是 mzstd,仓库在 https://github.com/M-Compressors/mzstd 。

帖子对比了两条已有路径。zstd crate 绑定 C 的 libzstd,构建要带 C 工具链,依赖树里有 unsafe FFI,目标放到 wasm 或嵌入式时会多一层构建成本。ruzstd 是纯 Rust,解码器可用,它的 README 写编码器还没到 C 的速度、压缩率和可配置性,预设大致对应 level 1、3、7、11。

mzstd 的编码器移植自参考实现。level 范围是 -131072 到 22,支持 long distance matching 和字典,压缩率与 C 相同。SIMD 通过 fearless_simd 在运行时选择,不要求 target-cpu=native。对照 C zstd 1.5.7,作者机器上压缩中位数约 1.1 倍,解压中位数约 1.02 倍。明文的快速 level 慢 6% 到 11%,高可压缩文本的解码最多慢约 20%。基准表和原始 CSV 在仓库里。作者的机器是 WSL2 上的 i7-13700KF。

API 有一次性 compress / decompress,也有 Read/Write 适配器和增量 session。session 接收输入和输出缓冲,返回处理进度,自己不持有 I/O。可以 no_std + alloc。并行压缩把一帧拆成任务,交给调用方已有的执行器,包括 scoped threads、rayon 或 tokio 的 blocking pool。crate 不自己创建线程。作者写,这是为了在 nginx 自己的线程池里跑压缩,并且已经在几个生产服务的 nginx 模块里使用。

crate 里没有 unsafe。差分测试对照 C zstd 的每个 level 和大量随机参数组合。AFL++ 覆盖编码器、解码器和流式 session。尚未支持 legacy v0.x 帧、无 magic 帧,以及一部分进阶参数。评论里作者补充,解码器把内存分配失败当作错误返回,编码器还没有。

同一条评论里,作者贴了 lzbench 上 C 库的对照:zstd 1.5.7 的 -22 压缩 1.99 MB/s、解压 1087 MB/s、压缩后 52284290 字节、压缩比 24.67;brotli 1.2.0 的 -11 压缩 0.56 MB/s、解压 383 MB/s、压缩后 50407795 字节、压缩比 23.78。作者写 Rust 实现会接近这些数。

示例代码:

use mzstd::{Compressor, Decompressor, EncoderConfig, Level};

let mut encoder = Compressor::new(EncoderConfig::default().with_level(Level::try_from(19)?))?;
let compressed = encoder.compress(b"hello, hello, hello")?;
let restored = Decompressor::default().decompress(&compressed)?;

原文链接:https://github.com/M-Compressors/mzstd


From Rust中文社区 Mike

社区学习交流平台订阅:

评论区

写评论

还没有评论

1 共 0 条评论, 1 页