文章摘要
经过一年半的努力,Roc编译器团队将30万行Rust代码重写为Zig,近期实现了与原编译器功能对等的里程碑。这一进展使团队能够更新WASM-4游戏Rocci Bird,展示了新编译器的实际应用。
文章总结
好的,这是对原文主要内容的中文重述,保留了关键细节,并删减了与主题无关的感谢名单和部分技术细节。
标题:我们的 Rust 到 Zig 重写进展如何
核心内容:
Roc 语言的编译器团队在过去一年半的时间里,将其 30 万行 Rust 代码重写为 Zig 语言。近期,他们达到了一个激动人心的里程碑:新编译器在功能上与旧编译器完全一致。
为何重写?
- 架构问题:Roc 编译器需要实现“多态去函数化”这一高级优化,但原有架构存在根本性缺陷,导致难以修复的 bug。一个原型证明,问题根源跨越多个编译阶段,需要重写大部分编译器。
- 团队共识:多位贡献者因其他原因也计划重写编译器的不同部分。与其进行“忒修斯之船”式的逐步替换,不如进行一次彻底的重写。
为何选择 Zig 而非 Rust?
团队主要基于以下四点考虑:
- 构建速度:Rust 的
cargo构建时间(即使是增量构建)是主要痛点,且随着代码库增长而恶化。团队预期 Zig 的构建会快得多。 - 内存控制:编译器在编译过程中使用多种不同的内存分配器(尤其是区域分配器)和“结构体数组”布局。Rust 的生态系统普遍假设使用单一全局分配器,而 Zig 的生态系统则天然支持细粒度的分配器。
- 生态相关性:虽然 Rust 生态整体更大,但两者中与编译器特定需求相关的包都很少。在团队需要的特定领域(如更快的 LLVM 位码生成方式),Zig 有现成的代码。
- 内存不安全辅助:编译器需要大量执行内存不安全操作(如生成机器码)。Rust 的
unsafe块设计用于隔离少量此类代码,但团队需要大量使用。Zig 提供了更多工具来帮助正确编写内存不安全代码。
重写后的实际体验:
- 内存安全:新编译器(使用 Zig 的
ReleaseFast模式)在实践中表现良好。在数百个 bug 报告中,仅有 2 个是编译器自身的内存安全问题(均为文件名渲染错误,Rust 的借用检查器本可捕获)。其余内存损坏 bug 均源于编译器生成的代码错误(误编译)。团队认为,选择哪种语言对项目实际影响不大,因为他们的主要风险在于编译输出,而非编译器自身。 - 构建速度:Zig 的增量构建速度极快(约 35 毫秒),远超 Rust(即使 Rust 的构建时间在同期内也大幅改善)。但由于 Zig 稳定版的一个 bug,团队目前尚未完全享受到这一优势,预计下一个稳定版发布后将能实现。
- 内存控制:新编译器采用“零解析反序列化”技术,将数据结构以数组和索引形式直接写入磁盘,加载时无需解析,速度极快。这种技术依赖于“无指针”编程风格,而 Zig 的生态系统对此支持更好。Rust 的借用检查器无法解决“哪个索引对应哪个数组”的问题,而
unsafe的广泛使用也削弱了其安全优势。 - 生态相关性:Zig 的生态系统(如传递分配器)更符合 Roc 编译器的需求。团队还复用了 Zig 编译器中的 LLVM 位码序列化代码,从而避免了直接依赖 LLVM C++ 库及其破坏性 API 变更带来的升级痛苦。
对 Rust 的怀念:
- 测试中的自动内存分配与释放。
- 参数多态和特设多态(ad-hoc polymorphism)。
- 私有结构体字段。
unsafe和借用检查器带来的心理安全感。- 更少的死代码。
- 优秀的向后兼容性。
对 Zig 的喜爱:
- 没有宏,许多问题可通过
comptime和普通函数解决。 - 对数据布局的精细控制(如非 2 的幂的整数类型、压缩结构体)。
- 无与伦比的构建工具链。
- 优雅的错误处理策略(将堆分配失败视为普通用户空间错误)。
- 以分配器为核心的 API 设计和高性能编译器生态。
总结与展望:
团队对选择 Zig 进行重写感到非常满意。新编译器解锁了热代码加载、跨平台编译、模式匹配中的字符串插值等新功能,且性能优异。他们计划在今年晚些时候发布 Roc 语言的第一个正式版本(0.1.0)。
评论总结
根据评论内容,总结如下:
主要观点与论据:
Zig增量构建速度是核心优势
- 评论2(onlyrealcuzzo):“Zig's incremental builds are DEFINITELY a killer feature.”
- 评论3(KoleSeise1277):“The 35ms incremental rebuild is the part that sold me.”
多位用户认为Zig的快速增量编译(如35ms)是吸引人的关键特性,甚至可能促使开发者从Rust迁移。
对Zig内存安全性的质疑
- 评论5(landr0id):“I have seen no evidence that it catches any type of use-after-free including double-free.”
用户指出Zig文档未明确提及“use-after-free”检测,其DebugAllocator在发布版本中也不可靠,质疑其安全声明。
- 评论5(landr0id):“I have seen no evidence that it catches any type of use-after-free including double-free.”
Rust与Zig的权衡:安全 vs. 速度
- 评论2(onlyrealcuzzo):“I want to go fast, but I don't want to go fast just to shoot my foot off.”
- 评论8(devl1xbe):“Zig is a pre-1.0 language while Rust is post-1.0. This alone settles which one to pick.”
部分用户认为Rust的成熟生态和稳定性更重要,而Zig的快速构建可能以牺牲安全性为代价。
对编译器实现语言的讨论
- 评论6(arthurbrown):“Interesting that OCaml was flexible... but not chosen as the implementation language.”
用户对Roc编译器从OCaml转向Zig表示好奇,并质疑内存控制对编译器是否必要。
- 评论6(arthurbrown):“Interesting that OCaml was flexible... but not chosen as the implementation language.”
对Rust重写趋势的预测
- 评论7(up2isomorphism):“I think there will soon be a wave of rewriting rust to language X coming up.”
用户预测可能出现从Rust迁移到其他语言(如Zig)的潮流。
- 评论7(up2isomorphism):“I think there will soon be a wave of rewriting rust to language X coming up.”
平衡性说明:
- 支持Zig的观点强调其增量构建速度(评论2、3)和跨平台能力(评论6)。
- 反对观点则关注Zig的安全性不足(评论5)、生态不成熟(评论8)以及Rust的稳定性优势(评论2、8)。
- 中立评论(评论4、6)指出编译器实现中“unsafe”代码的必要性有限,并质疑Zig在编译器领域的适用性。