2025年2月,函数式编程语言 Roc 的创始人 Richard Feldman 在一个 Gist 里写下了一段让整个系统编程圈炸锅的话:他们决定把 Roc 编译器整个推倒重写——从 Rust 换成 Zig。这不是一个边角小项目,而是三十多万行(300K+ LOC)的成熟编译器代码。一年多后的 GOTO 2026 大会上,他和教育者 Anjana Vakil 坐下来,把这次"自我推翻"的完整故事讲了一遍,这就是《Roc & Zig: A Compiler Rewrite Story》。
这个视频值得每个写代码的人看,不是因为 Rust vs Zig 的口水战,而是因为它罕见地展示了一个严肃工程团队如何在"语言宗教战争"里做冷静的成本核算:什么时候内存安全是必需品?什么时候它只是个累赘?编译速度到底值多少钱?更妙的是,这次重写恰好赶上 AI 编程助手从"有点用"变成"颠覆性"的一年,于是视频还顺带回答了一个所有人都在问的问题——AI 写出来的代码,到底能不能信?我的解读会区分视频原话和我的延伸分析,你可以当成一份"决策复盘"来读。
| 项目 | 内容 |
|---|---|
| 视频标题 | Roc & Zig: A Compiler Rewrite Story • Anjana Vakil & Richard Feldman • GOTO 2026 |
| 频道 | GOTO Conferences |
| 发布日期 | 2026年5月11日 |
| 时长 | 对话形式(GOTO Unscripted,约半小时) |
| 播放量 | 约4800(发布2个月;但其底层决定在 Hacker News 拿下 359 分/301 评论,Lobsters 108 赞/48 评论,是 2025 年编程圈最热话题之一) |
| 核心主题 | Roc 编译器从 Rust 重写为 Zig 的技术决策,叠加 AI 编程助手时代的软件质量思考 |
| 主讲人 | Richard Feldman(Roc 创始人,现 Zed Industries,《Elm in Action》作者)、Anjana Vakil(独立开发者教育者) |
视频的主线很清楚:Roc 是一门主打"fast, friendly, functional"的函数式语言,它有个独特的"平台(platform)"设计——副作用由可替换的宿主运行时提供,语言本身保持纯粹。它的编译器原本用 Rust 写,规模已经长到 30 万行以上。
这里要补一个视频里点到但没展开的背景(我的延伸):Roc 和 Zig 其实早有"暧昧"。Roc 的标准库(standard library)早就从 Rust 重写成 Zig 了,社区里有个俏皮的说法叫"Rust in the sheets, Zig in the streets"——编译器用 Rust,对外暴露的标准库用 Zig。所以这次把编译器也换成 Zig,不是失恋后盲目相亲,而是一次有预谋的"全面倒戈"。
Richard Feldman 在 Gist 里的原话是:"we have decided to do a scratch-rewrite in a different language—namely, Zig."(我们决定用另一种语言——也就是 Zig——做一次从零重写。)关键词是 scratch-rewrite:不是渐进迁移,是推倒重来。三十万行代码说重写就重写,这个体量本身就是一种表态——他们一定是对现状极其不满。
整个决策里最锋利的一刀,是 Feldman 对 Rust 核心卖点的直接拆解。他的原话大致是:对很多项目,Rust 的内存安全是大好处;但"Roc 的编译器不是其中之一"(Roc's compiler is not one of those projects)。
理由很硬核(视频原话+我的注解):编译器这种程序,内存模型其实极其简单——它大量使用 arena 分配器(一次性开辟一大块内存,编译完整体释放),字符串会在早期就被 intern(去重 intern 到一张表里),而且每个数据结构都被隔离在编译的某一个特定阶段。换句话说,生命周期根本不复杂,大多是"全局有效"。
我的延伸:这意味着 Rust 借用检查器(borrow checker)花大力气要你标注的那些 lifetime,在编译器这个场景里几乎全是"全局寿命"的废话标注。Roc 贡献者 Brendan Hansknecht(Lobsters ID: bhansconnect)的原话印证了这一点:"Rust made us document a ton of lifetimes that were really unimportant due to practically being global."(Rust 让我们标注了一大堆其实毫无意义的生命周期,因为它们实际上就是全局的。)这是一个极具杀伤力的论点:当被守护的东西根本不存在时,守卫本身就是纯成本。
如果说安全是"伪需求",那"真痛点"是什么?两个字:编译速度。视频和社区讨论里给出了 Roc 编译器在 M1 Mac 上的实测数据(贡献者 Brendan 提供):
我的延伸:请想象一下这个反馈回路——你改一行代码,盯着进度条发 17 秒呆,然后才能看到结果。Oils 项目的作者 andyc 在 Lobsters 上一针见血:"I also can't deal with slow compile times -- it takes me out of the zone."(我也受不了慢编译——它会把你从心流状态里生生拽出来。)对开源项目尤其致命,因为开源"应该是有趣的",慢编译是在谋杀乐趣。
更阴险的是 Feldman 指出的第二层伤害(视频原话):Rust 的编译基本单元是 crate,所以你被反向激励——按"什么能让编译更快"来组织代码,而不是按"什么对作者最合理"来组织。当两者冲突时,你要么牺牲反馈速度,要么牺牲代码结构。这种"工具逼着你扭曲设计"的痛,写过大型 Rust 项目的人都懂。Brendan 也坦承:编译器是"organically grew"(野蛮生长)的,结构本身就不利于编译速度,"即使重写成 Rust 也会快不少"——但团队判断,既然要重写,不如顺便换门更合手的语言。
视频讲的是"我们为什么换",但"Zig 为什么本质上更可能快"这个问题,是 rust-analyzer 作者 matklad 在 Lobsters 上给出的一组分析,我觉得是整个讨论里含金量最高的部分(这是社区延伸,非视频内容):
第一,链接模型。 这是 matklad 称之为"皇帝没穿衣服"(emperor without clothes)的点。C 的编译模型是:每个 .c 文件独立编译成目标文件,再链接。但这套模型和泛型/单子化(monomorphization)天生冲突——fn mystery<T>(t: T) 在没看到具体类型前根本编不出来。Rust 和 C++ 的做法是:在每个用了 mystery::<i32> 的编译单元里各编一份,最后让链接器把重复副本删掉。这是巨大的浪费。Zig 的解法是不做"独立编译"——所有东西一起编译,单子化在全局层面去重。(steveklabnik 补充:Zig 还做"tree shaking",先找活代码再编,而不是先全编再删死代码。)
第二,解析可并行。 Zig 的解析是"embarrassingly parallel"(天然可并行)的;而 Rust 的解析纠缠着名称解析、宏展开,还有过程宏(proc-macro)会执行任意代码,根本没法痛快并行。
第三,comptime < 宏。 Zig 的编译期反射(comptime)从原理上就比 Rust 的语法宏(尤其是过程宏)给编译器制造的活儿少。
第四,性能是架构级目标。 matklad 的原话:"The compiler is architected with performance as a primary goal, rather than a nice-to-have."(编译器把性能当作首要目标来架构,而不是"有了更好"。)他还下了个赌注:"I am 0.7 sure that Zig+native backend will run circles around Rust+cranelift."(我有七成把握,Zig+原生后端会把 Rust+cranelift 甩开几条街。)
我的注解:这里有个诚实的 caveat——matklad 也承认,截至 Zig 0.13,Zig 编译还没真的那么快(比如 TigerBeetle 改一行还要 7 秒),因为只要还依赖 LLVM,就测不出其他部分的真本事。Richard Feldman 自己也澄清:他对比的是 Zig 尚未稳定的特性(自托管 x86_64 后端等),赌的是这些特性会在 Roc 的 Zig 代码膨胀到产生痛点之前稳定下来。所以这是一个面向未来的下注,不是当下的既成事实。这个区分很重要,别被"Zig 已经秒杀 Rust"的标题党带偏。
视频和 Gist 里有个常被忽略但极有思想性的点:Roc 之前用 Rust 生态里的 Inkwell(LLVM API 的封装),但他们"actively would prefer to switch to Zig's direct generation of LLVM bitcode"(主动想换成 Zig 直接生成 LLVM bitcode)。Feldman 说"Zig has the only known implementation of that approach"(Zig 是已知唯一这么做的)。
我的延伸:这件事的妙处在于——LLVM 的公开 C++ API 每个版本都在变,但它的 bitcode(字节码)有较强的向后兼容。直出 bitcode 意味着升级 LLVM 时你的代码生成层基本不用动。Lobsters 用户 "5-" 把这上升到一个哲学高度:这是在对抗"用库替代协议"的危险趋势——传统协议设计出来就是为了让多方独立实现的,而库/框架把 API 和实现搅在一起,事实上逼出单一实现。既然有 LLVM IR(无论 bitcode 还是文本形式)这个现成的"协议",为什么不用?steveklabnik 冷静地泼了盆水:"LLVM IR is not stable"(LLVM IR 并不稳定)——所以它是不是"好协议"仍有争议。但方向上的吸引力是实在的。
还有个更早的伏笔(社区用户 doug-moen 补充):Roc 的标准库当初从 Rust 换成 Zig,一个关键原因就是——标准库要和生成的机器码/LLVM bitcode 直接交互,Rust 代码不可避免地要满地 unsafe,这等于让 Rust 最大的卖点直接失效。既然卖点失效,Zig 更快的编译就成了净收益。
Feldman 列了一串"在 Rust 里能做但很痛、在 Zig 里很顺手"的特性,视频里是当作佐证带的,我挑几个最有代表性的展开(视频原话):
u27 存真正的索引(因为知道永不会超过 2^27),3 位存一个小枚举,2 位存两个布尔。Rust 里你得用 u32 加位移手搓,能做,但"much nicer to do in Zig"。allocator 显式传递:Zig 围绕"传递分配器"来设计内存管理,这正是 Roc 想要的模型,而 Rust 没有。
musl 静态链接:Zig 工具链让编译 musl libc 静态链接的 Linux 二进制变得容易,这样 Roc 能跑在任何发行版上(包括容器里的 Alpine,而当前 Rust 编译器做不到)。Zig 编译器自己就是这么干的——边打包 LLVM(用 musl 从源码构建)边静态链接,正好是 Roc 需要的,且 Rust 生态里没有等价物。
我的判断:单独拎出来,每个都是"小事";但叠加起来,它们描绘出一个图景——Zig 的设计恰好和"写一个编译器"这件事的需求曲线吻合。这不是 Zig 全面碾压 Rust,而是场景匹配度的胜利。
这是 GOTO 2026 这场对话区别于 2025 年那波讨论的"新料",也是视频最值得看的部分。Feldman 描述了 AI 在这次重写中角色的演变(视频原话):短短 12 个月里,AI 从"可靠的机械搬运工"(做测试移植这种 grunt work,可靠但上限低),进化到能在更难的架构问题上真正参与协作。
但视频最有价值的洞察是这一句(我的提炼):护栏(guardrails)不在 prompt 里,在代码里。 Feldman 说,你在 prompt 里写"never do this"(千万别这么做),AI 会"cheerfully disregard"(愉快地无视)。真正管用的是把不变量(invariants)和自动化反馈回路写进代码本身——让代码在 AI 跑偏时自动把它逮回来,而不是指望一句指令它能听。
我的延伸:这其实是把"防御性编程"从"防人"升级到"防 AI"。人对规范是有默契的,AI 没有默契、只有上下文。所以未来的高质量代码库,会越来越多地用可执行的不变量、fuzzing、类型约束、CI 门禁来当"AI 的围栏",而不是依赖文档和注释。Richard 还透露 Roc 新编译器会从第一天就上 fuzzing(含内存泄漏检测)——因为之前 Rust 编译器"上手太晚",fuzzer 一跑就崩在无数边角案例上。
视频后半段是对 AI 时代软件质量的思辨(视频原话):两人都警惕即将到来的 "slop"(大规模生产的、平庸有 bug 的 AI 软件)浪潮。但 Feldman 给了个反直觉的判断——竞争压力可能反而把质量顶上去:"如果满世界都是 slop,那不是 slop 的产品会异常显眼。" Anjana 用了个漂亮类比:就像你会花高价买一根确定不会起火的 USB-C 线,未来开发者和用户会越来越向"能担保的品牌和社区"靠拢。他们的结论是:开源贡献模式需要新机制来应对 AI 时代,而计划在 2026 年底前发布的 Roc v1,将是一块试金石。
graph TD
A["Roc 编译器重写: Rust → Zig<br/>30万行推倒重来"] --> B{"为何要重写?"}
B --> C["编译时间痛点(真凶)"]
B --> D["Rust 安全是伪需求"]
B --> E["生态错配"]
C --> C1["改一行等17秒/全量2分钟"]
C --> C2["crate模型逼你按编译速度组织代码"]
D --> D1["arena内存 + 全局生命周期"]
D --> D2["borrow checker 在解不存在的问题"]
D --> D3["stdlib 满地 unsafe → 卖点失效"]
E --> E1["Inkwell → 直出 LLVM bitcode"]
E --> E2["musl 静态链接 / 跨发行版"]
B --> F{"Zig 凭什么更好?"}
F --> F1["全局单子化去重 · 不分编译单元"]
F --> F2["tree-shaking 只编活代码"]
F --> F3["comptime < 宏 · 解析可并行"]
F --> F4["自托管后端摆脱 LLVM"]
F --> F5["allocator传递 · SoA · 位打包 · tagless union"]
G["2026 新主线: AI 参与重写"] --> G1["从搬运工 → 架构协作"]
G --> G2["护栏在代码不在 prompt"]
G --> G3["slop 时代 · 质量反成稀缺品"]
A --> H["结局: Roc v1 2026年底前 · 试金石"]
对正在选语言的团队:别再问"X 好还是 Y 好",要问"我的场景曲线长什么样"。 Roc 这次决策最大的教益不是"Zig 比 Rust 好",而是一套可复用的评估框架:把语言特性逐条对照你项目的真实需求——你的内存生命周期复杂吗?你需要静态链接跨发行版二进制吗?你的反馈回路对几秒敏感吗?你的代码会野蛮生长到 30 万行吗?当 Rust 的两大卖点(内存安全、大生态)在你的场景里双双"不适用"时,剩下的就全是成本(慢编译、lifetime 标注负担、crate 组织扭曲)。卖点失效 = 该换。
对所有写 Rust 的人:编译速度是设计决策,不是优化尾巴。 matklad 的分析点醒一件事——Rust 慢编译的根子在编译模型(单子化重复编译+链接器去重、宏执行任意代码、crate 单元),是架构级的,靠 mold/lld/sccache 这类工具只能擦边。Brendan 证言:Roc 试过 mold,"didn't move the needle noticeably"(几乎没用)。所以大型 Rust 项目要从第一天就把"减少泛型滥用、控制 crate 粒度、少引重依赖(serde 之流)"当一等公民来对待,而不是事后再补。
对所有人:在 AI 时代,把不变量写进代码,别写进 prompt。 这条启示的普适性远超编译器。无论你用什么语言,未来你的代码会有相当一部分由 AI 生成或修改。把"规则"留在自然语言里是脆弱的——AI 会愉快地无视。把规则变成类型、断言、fuzz target、CI 门禁、property-based test,让代码自己当裁判。Roc 新编译器"从第一天就 fuzz"的策略值得借鉴:护栏要前置,且必须是可执行的。
对技术决策者:敢于自我推翻是高级能力。 Richard Feldman 自己选了 Rust 起步,几年后又亲手推翻——这种"对过去的自己诚实"的勇气比"从一而终"更稀缺。一个还没发布 v1 的语言,恰恰是探索设计空间、允许推翻的最佳时机(社区用户 silby 的原话:在追求广泛采用之前探索实现的基本可能性,是合理的优先级)。等代码进了生产、有了 ABI 承诺,再想推翻就难如登天了。
Roc 弃 Rust 投 Zig,表面是语言之争,内核是一场教科书级的"按场景曲线做技术选型"——它告诉你:当一门语言的核心卖点在你的场景里失效时,编译慢这种"小痛"也会逼疯一个语言作者。
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
youtube_transcript.py[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
