过去一年,Trifecta Tech团队给Rust编译器提交了7个PR。不是优化文档,是直接改clippy和编译器本身。他们的数据压缩项目(zlib-rs、libbzip2-rs、libzstd-rs-sys)用Rust重写C代码时,发现等官方排期是死路——需要的功能太边缘,永远在todo list底部。
「等不是策略」,这是团队负责人Folkert de Vries的原话。他们选择了一条更费力的路:自己修。
从c2rust的"诅咒代码"开始
团队重度依赖c2rust,一个把C自动转Rust的工具。转出来的代码能跑,但风格诡异——指针算术满天飞,嵌套if像俄罗斯套娃。clippy(Rust的代码检查工具)能标记问题,甚至自动修复,但c2rust的产物有时候"邪门"到clippy修完直接编译报错。
一个典型bug:带括号的嵌套if会让clippy的collapsible_if规则给出错误建议。原代码长这样:
if true { (if true { () }) }
clippy建议改成「if true &&f true」,括号没消干净,逻辑直接崩。团队在PR #15304里修了这个边界情况。
更隐蔽的是ptr_offset_by_literal。c2rust喜欢生成foo.offset(4)这样的代码,团队新加了一条lint,自动改写成foo.add(4)。别小看这个替换——只用add不用sub的指针操作,后续转成Rust切片(slice)会容易得多。
这个PR (#15606)还牵出另一件事:团队发现ptr_offset_with_cast的实现已经技术债累累。正好赶上clippy功能冻结期,顺手在PR #15613里重构了。
编译器里的"幽灵类型"
工具链之外,团队还往Rust编译器本体里钻。
他们的压缩库大量用SIMD(单指令多数据,一种并行计算技术),但Rust的std::simd还在实验阶段,不稳定。更头疼的是bindgen——这个从C头文件生成Rust绑定的工具,对SIMD类型支持残缺。
bindgen会直接把C的SIMD类型映射成「某种整数数组」,类型信息全丢。团队需要手动告诉编译器「这128位数据其实是4个f32」,否则优化器看不懂,性能直接腰斩。
他们在PR #1567里给bindgen加了--with-derive-custom选项,允许用户注入自定义派生宏。现在生成的代码能带上#[repr(simd)],编译器终于知道该怎么优化了。
「我们不是在抱怨工具,是在补工具没覆盖的角落。」
稳定化十年老特性
最费时的战役是std::simd的稳定化推进。这个API 2014年就存在,2025年还在unstable(不稳定)状态。
团队的做法很务实:不是从头设计,是整理现有实现,写测试,补文档,把"能用的部分"和"必须再等等的部分"切开。Folkert de Vries将在RustWeek 2025上分享具体策略,题目就叫《Stabilizing decade-old features》。
一个细节:他们发现某些SIMD操作在特定架构上其实早就稳定,只是没人去推动标记。团队做了大量平台测试矩阵,把"安全区"划出来,让稳定化提案有数据支撑。
自己修,值不值?
算笔账:7个PR,平均每个从发现问题到合并,耗时2-4周。如果等官方,zlib-rs需要的内存对齐特性估计2026年都排不上。
更隐蔽的收益是团队能力的质变。现在他们能直接读LLVM中间表示,能在编译器报错信息里定位到具体哪行HIR(高级中间表示)生成错了。这些技能反哺到压缩库本身,最近一个优化让解压吞吐量提升了12%。
当然也有代价。维护私有fork期间,团队得自己跟踪nightly版本的breaking change。有一次Rust编译器内部API改名,他们花了整整两天做迁移。
「但比起功能被卡住,这点摩擦算便宜的。」
团队现在形成了一个固定节奏:每季度review一次"我们自己修了什么",把能上游化的推给官方,太特化的留在内部。zlib-rs的GitHub仓库里有个CONTRIBUTIONS.md,专门列这些"非业务代码"的产出。
最后一个PR是上周合并的:给clippy加了检测重复内存拷贝的lint。触发场景很边缘——只有c2rust生成的代码才会那样写。官方reviewer一开始觉得太niche,团队提供了真实项目的性能对比数据,最终说服合并。
Folkert de Vries在PR描述里写了一句:「This lint would have saved us 3 hours of debugging last month.」
如果你们的项目也被某个"太小众"的需求卡住,会选择自己动手,还是继续等?
热门跟贴