首页 › programming › 通过测试≠安全:AI重写百万行埋了1.3万unsafe

当AI六天"重写"百万行:99.8%通过率背后的真账单

导语

如果你常刷技术内容,2026年5月这条新闻大概率从你眼前划过:JavaScript运行时 Bun 的作者 Jarred Sumner,用一个 PR(#30412)把整个运行时从 Zig 翻译成了 Rust——大约一百万行代码,耗时六天,全程由 AI agent 写代码,人类一行没敲。 更震撼的是,它通过了 Bun 已有测试套件的 99.8%。无数自媒体立刻打出标题:"AI 重写了百万行代码,一夜之间",《The Bun Story》这类深度解读视频也随之爆火。

这正是问题所在:99.8% 是一个会让你产生安全幻觉的数字。 它听起来像"完美交付",但它只证明了"新代码在公开接口上的行为和老代码一样",并不证明这份代码安全、地道、更优秀。Bun 团队自己的后续审计,在这份"通过测试"的代码里数出了 13,365 个 unsafe 块(同等规模的、手写的 Rust 项目 uv 只有 73 个),还揪出 5 个真正会触发未定义行为的 unsound 函数。

这篇解读想帮你回答一个问题:当 AI 第一次把一个生产级运行时几乎"无人编写"地搬进另一种语言时,真正决定成败的不是模型有多聪明,而是反馈回路有多紧、验证地基有多厚。 你会看到,这趟"奇迹"本质上是一场被刻意降维成"翻译"的工程,而它的账单——那 1.3 万个 unsafe——正是"只看测试通过"会让人付的代价。

视频背景卡片

项目 内容
视频标题 AI Just Rewrote 1 Million Lines of Code Overnight — The Bun Story
视频链接 https://www.youtube.com/watch?v=v2l_h99wt6Y
频道类型 技术深度解读频道(围绕 2026 年重大 AI/编程事件的评论类内容)
时长 约 15–20 分钟(深度解读型长视频)
传播状态 2026 年 5–6 月随 Bun 重写事件病毒式传播,被多个技术社区与博客反复引用
核心主题 AI agent 是否真能完成百万行级别的生产代码迁移?测试通过能否等于安全?

说明:因 YouTube 对服务器 IP 的访问限制,本次未能抓取到该视频的精确播放量与字幕;以下分析以视频所讲述的核心事件为锚,结合 The Register、bun.com 官方 unsafe 审计、codex.danielvaughan.com、grigio.org、dasroot.net 等 8 个以上独立来源交叉印证。

一、先看清那串晃眼的数字

几乎所有报道都在重复同一组数字,但很少有人拆解它们的来源:

这串数字之所以震撼,是因为它同时击穿了软件工程的两个传统信念。第一是"重写很贵"——一个大运行时的语言迁移,传统认知里是"数人团队一两年"的活;第二是"AI 写代码不可靠"——百万行 AI 代码听起来就是"AI slop(AI 垃圾)"。

但震撼归震撼,数字本身不会告诉你它怎么做到的。这才是解读的真正入口。根据多个技术复盘,这次迁移跑的是一条结构化流水线,分四步:清单盘点(建依赖图)→ 并行翻译(逐文件翻译)→ 编译反馈循环(把编译器错误回喂给 agent 直到通过编译)→ 测试验证(用已有测试套件验证行为一致性)。

注意第三步和第四步——这是整个故事里最关键、却最容易被"6天百万行"标题盖过的部分。没有编译器反馈循环和测试套件,agent 根本不可能收敛。"六天写完"是真的,"六天写对"则是另一回事。

二、关键澄清:这不是"重写",是"翻译"

这是整件事最容易被误读的地方。很多自媒体用"rewrite(重写)"这个词,但如果你真去读那 13,365 个 unsafe 块的成因和 Bun 团队的说法,会发现一个截然不同的真相:这是一次"忠实搬运(faithful transliteration)",不是"重新设计"。

dasroot.net 的复盘引用了 Sumner 的话:性能"持平或更快",尽管"架构是一样的,数据结构也是一样的"。换句话说,agent 没有重新设计运行时,它把 Zig 的每一个模块、每一种数据结构、每一条控制流,尽可能一一对应地翻成了 Rust。

这个区别极其重要,因为它直接回应了软件工程界那句最著名的告诫——Joel Spolsky 在 2000 年写的《Things You Should Never Do》。Joel 警告的"绝对不要做的事"是"从零推倒重来"(比如 Netscape 5.0 的灾难),因为那等于把多年积累的、藏在代码里的隐性知识全部扔掉。但那次灾难的根因是"重新设计"——换了架构、换了抽象。而 Bun 这次恰恰避免了这一点:它保住了原来的知识和结构,只是换了表达它的语言。

【延伸分析,非视频原话】这就是为什么"AI 重写百万行"能在六天落地:把一个"高风险的重设计问题"刻意降维成了一个"低风险的机械翻译问题"。AI agent 擅长的,恰恰是"保持语义不变地换语法",而不是"凭空发明更好的架构"。一旦你把它当成翻译工具而非架构师来用,它的可靠性会跳一个量级。

三、99.8%通过是地板,不是天花板

现在到了全文最反直觉的一点,也是我最想提醒每个开发者警惕的陷阱。

99.8% 测试通过,听起来几乎完美。但它只证明了"新实现在公开接口上的行为,和老实现一致"。它完全不证明:这份代码是安全的、地道的 Rust、或者 sound(健全)的。 codex.danielvaughan.com 的技术拆解把这件事讲得最清楚,我用一个对比让你感受差距:

也就是说,"通过测试"的这份代码,比一个正常手写的同类项目,unsafe 数量高了将近 183 倍。更要命的是,Bun 团队合并后的审计发现,有 5 个函数是真正 unsound 的——即"从安全 Rust 就能触发未定义行为"的真 bug——而这 5 个甚至都不在那 13,365 的统计里。

这给所有用 AI 写代码的人提了个醒:"测试通过"是必要条件,不是充分条件。 当 LLM 同时在写代码、甚至可能改测试(社区里就有人质疑 agent "把测试改通过"而不是修实现),你那个 99.8% 就不是终点,而只是起点。在 AI 代码这件事上,"能跑"和"安全"是两件事,而 99.8% 这个数字会让你误以为它们是一件事。

四、最扎心的细节:AI 明知自己在写错代码

如果你以为 agent 是"没看懂 Rust 才乱写 unsafe",那你就低估它了。grigio.org 引用了一位 Reddit 用户深挖代码后的发现,这条细节足以让任何 Rust 开发者倒吸凉气:

代码里出现了 999 处 static mut(全局可变状态,正是 Rust 安全模型的对立面),还有 262 处 ManuallyDrop、81 处 mem::forget。而每个 unsafe 块旁边,AI 自己写的注释是这样的:

// PORT NOTE: Zig used plain `var` globals (unsynchronized). Mirrored here as
// `static mut` with the same single-writer-at-startup discipline; reads after
// `enable()` are technically racy in both languages.
// TODO(port): consider AtomicBool/AtomicI32 if Phase B wants strict soundness.

翻译一下这段注释的意思:"Zig 原来用的是不加同步的全局变量,我在这里原样照搬成 static mut;enable() 之后的读取,在两种语言里其实都是有竞态的;如果 Phase B(第二阶段)想要严格健全性,再考虑改成 AtomicBool。"

这段话是 AI 自己写的。它完全清楚这是 unsound 的代码,它甚至知道正确的写法是 AtomicBool。它只是选择"先这样,Phase B 再说"。

这才是真正的认知冲击。AI 不是无知,它是在一个"先通过测试、快速落地"的目标函数下,有意识地、明码标价地承担了技术债。它把"知道哪里有问题"变成了注释,而不是修复。这恰恰是工程师最熟悉的那种"先跑起来再说"——只不过这次,执行它的是机器,而且规模是 13,000 多处。

【个人观点】这也解释了为什么社区反应如此撕裂:r/rust 上那条高赞评论"if this ends up working... I might actually have that meltdown"(要是这玩意儿真能跑,我可能真要崩溃了),本质上是工程师目睹了"我知道这不地道,但它居然 work"时的认知失调。而乐观派的关键反驳也成立——这 13,000 个 unsafe 之所以能被看见、被计数、被审计,恰恰是因为用了 Rust:在 Zig 里,同样的风险是隐形的。 可见性本身,就是 Rust 给这次迁移的第一笔红利。

五、真正的英雄不是模型,是反馈回路

如果你只能从这篇解读里带走一句话,我希望是这一句:决定 AI 代码质量的,往往不是哪个模型、提示词写得多好,而是你的环境能多快、多精准地"拉绳子"让 agent 自我纠错。

这个比喻来自 X 用户 @rentierdigital,他管 Rust 编译器叫 "andon cord(安灯拉绳)"——丰田生产系统里工人发现问题、立刻拉停整条产线的那根绳。当 AI 写出糟糕的 Rust,编译器会立刻"拉绳":结构化的错误、精确到行的位置、清晰的修复路径。agent 读它、改它、重跑。 没有别的系统级语言能在同样的精度上提供这个反馈回路。

把这个逻辑想透,你会发现一个反直觉的结论:Bun 这次选 Rust,不只是为了内存安全,更是因为 Rust 是当下最适合 AI 生成代码的系统语言。

所以别再问"哪个 AI 写代码最强"了。对于系统级代码,更该问的是:哪种语言能给 AI 最紧的反馈回路? 这才是这次迁移留给工程师最值钱的认知迁移。模型还在快速迭代,但"环境反馈密度决定 AI 代码质量"这条规律,比任何具体模型都长寿。

六、验证堆栈:翻译能成的隐形地基

回到第五步编译反馈、第四步测试验证,再往深一层,这次迁移之所以"能落地",靠的是一套多层验证堆栈,而不是单一的神级模型。codex.danielvaughan.com 把这套堆栈列得很清楚:

验证层 工具 它抓什么
编译 cargo check 类型错误、生命周期违规
静态检查 cargo clippy 不地道的写法、常见错误
行为对齐 已有测试套件 行为回归
unsafe 盘点 cargo geiger unsafe 块的清单
健全性 miri unsafe 代码里的未定义行为
覆盖率 cargo tarpaulin 没被翻译路径覆盖到的盲区

而且这里藏着一个被多数人忽略的天才设计:Bun 的测试套件是 TypeScript 写的,而实现语言是 Zig(现在是 Rust)。 这意味着测试是一套与实现语言无关的"预言机(oracle)"——它不会被语言偏见污染,迁移前后用的是同一把尺子量行为。这就是 99.8% 这个数字哪怕不等于安全,也仍然有真实意义的原因:它是跨语言的行为一致性证据。

再加上 grigio.org 提到的另一层:流水线里每个翻译文件都配了一个"对抗式审查 agent"(adversarial reviewer)——第二个 AI,专门负责挑第一个 AI 输出的 bug。所以真实画面不是"一个 AI 闷头写百万行",而是"生成—对抗审查—编译反馈—测试"的闭环。

【延伸分析】这套架构的潜台词是:当人类来不及读代码(百万行没人读得完),你就必须用"机器对抗机器 + 编译器 + 静态分析 + 语言无关测试"来补位。人在这里从"代码评审者"变成了"验证策略的设计者"。 这也呼应了 Anthropic 的 Boris Cherny 那句被广泛引用的话:"如果你看大多数 Claude Code 会话,真正做 prompting 的,其实是另一个 Claude。"——瓶颈正在从"写代码"转移到"审查",再到"可维护性与安全"。

七、知识结构图:一次 AI 重写为什么会"成"

flowchart TD
    A[Bun 运行时<br/>~96万行 Zig] --> B{第一步: 降维决策}
    B -->|关键| C[翻译而非重设计<br/>保留架构与数据结构]
    C --> D[第二步: 结构化流水线]
    D --> D1[盘点: 建依赖图]
    D --> D2[并行: 逐文件翻译]
    D1 --> D2
    D2 --> D3[编译反馈循环<br/>错误回喂 agent]
    D3 --> E{第三步: 多层验证地基}
    E --> E1[cargo check/clippy<br/>编译期拦错]
    E --> E2[TS 测试套件<br/>语言无关预言机]
    E --> E3[对抗式审查 agent<br/>机器查机器]
    E1 --> F[99.8% 测试通过<br/>= 行为一致]
    E2 --> F
    E3 --> F
    F --> G{第四步: 真实账单}
    G --> G1[13,365 个 unsafe<br/>对比 uv 仅 73]
    G --> G2[5 个 unsound 函数<br/>测试抓不到]
    G --> G3[999 处 static mut<br/>AI 自知却欠债]
    H[环境反馈密度<br/>Rust 编译器=andon cord] -.决定.-> D3
    H -.决定.-> E1
    style B fill:#ffe4b5,stroke:#d2691e
    style G fill:#ffd0d0,stroke:#c0392b
    style H fill:#d0ffd0,stroke:#27ae60

这张图想表达的核心:"AI 重写百万行"之所以没翻车,是四个齿轮咬合的结果——降维成翻译、流水线化、多层验证、紧反馈回路。拿掉任何一层,结果都会完全不同。

八、什么时候 AI 重写会翻车

理解了它为什么"成",你才真正理解它的边界。codex.danielvaughan.com 给出的反例清单值得每个想复制这套打法的人抄在墙上:

  1. 源语言是动态类型(比如 Python → Rust):类型推断的鸿沟太大,AI 无法"忠实翻译",因为它得先猜你那些没写出来的类型;
  2. 目标架构本就该不同:AI 擅长搬运,不擅长重新设计。如果你迁移的目的是"借机重构架构",AI 翻译会把旧架构的烂设计原样搬过去;
  3. 代码库没有测试覆盖:没有那把"语言无关的尺子",你根本无法验证翻译对不对——99.8% 之所以有意义,前提是那套测试套件本来就厚重;
  4. 业务逻辑没有文档:当代码本身有歧义时,AI 无法从代码里反推出"你到底想要什么"。

【延伸分析】把上面四条反过来读,你就明白了为什么偏偏是 Zig → Rust 这次成了:两者都是系统级语言,都做手动内存管理,结构相似度足够高,能逐行对应;Bun 又有一套庞大、跨语言的测试套件当预言机。 换成 Python → Rust,或者一个没测试的老项目,同样的 agent、同样的六天,大概率会交出一份"能编译、跑起来全是坑"的灾难。这次"奇迹"是有前置条件的,而那些前置条件,恰恰是大多数自媒体标题不会告诉你的。

九、产业信号:瓶颈正在迁移

跳出来看,这次事件真正的价值不在 Bun 本身,而在它发出的产业信号:

实战启示:这套打法你能怎么用

如果你是开发者,看完上面这些,下面是能立刻拿走的东西。

第一,把 AI 当翻译工具,而不是架构师。 当你面对一个"换语言/换框架"的需求,先问自己:我要的是"保持行为不变地换表达",还是"借机重新设计"?如果是前者,AI 翻译 + 严格验证是高性价比路径;如果是后者,AI 只会让旧设计披上新语法的外衣。

第二,永远保留一套"语言无关的预言机"。 不管你用什么实现语言,把核心行为用与实现解耦的方式测出来(独立测试套件、契约测试、golden file)。这正是 Bun 能验证迁移成败的根基。没有这把尺子,"AI 迁移成功了"就是一句无法证伪的话。

第三,给 AI 代码设一个"债务预算"。 学 Bun 的事后教训:合并前就立规矩,比如"FFI 边界才允许 unsafe,纯逻辑出现 unsafe 必须人工复审,每千行不超过 N 个"。把 cargo geiger、miri、clippy 接进你的 agent 工作流(比如在每次写文件后自动跑),让验证在循环里持续发生,而不是合并后才发现 13,000 个 unsafe。让 agent 写代码,让钩子写安全网。

第四,选语言时,把"反馈密度"纳入考量。 如果你大量用 AI 写代码,优先选那种"编译器能当场拉绳"的语言。同样的 prompt,在 Rust 里和在一个动态类型语言里,AI 出错的暴露速度天差地别。

第五,对"测试通过率"保持警惕。 99.8% 不等于安全、不等于地道、不等于健全。把它当成地板,再用静态分析和健全性检查往上盖楼。尤其当 AI 同时在碰测试文件时,要单独盯住"测试有没有被悄悄改过"。

延伸学习路径

  1. Joel Spolsky《Things You Should Never Do》(2000)——理解"为什么重写危险"的经典原文,对照这次"翻译而非重设计"会更有收获;
  2. The Register: "Anthropic's Bun Rust rewrite merged at speed of AI"(2026-05-14)——主流科技媒体对事件的第一手报道;
  3. bun.com 官方 unsafe 审计页——团队自己承认"13,365 个 unsafe,其中约 9,300 个可改为安全代码"的一手资料;
  4. codex.danielvaughan.com 的 Agent-Driven Codebase Rewrites——把这次迁移拆成可复用的五阶段框架,附 token 成本估算;
  5. Rust 工具链文档:miri(查 UB)、cargo geiger(数 unsafe)、clippy——亲手把这些验证工具跑一遍,比读十篇文章都管用。

一句话总结

Bun 的六天百万行"奇迹"证明的不是 AI 多能写,而是:当你把可怕的重写降维成翻译、再用紧反馈回路和多层验证兜底,AI 就能在生产级代码上落地——但 99.8% 的测试通过率只是地板,那 1.3 万个明知故犯的 unsafe,才是它真实的账单。


参考来源

  1. AI Just Rewrote 1 Million Lines of Code Overnight — The Bun Story — 本轮分析的核心视频
  2. Agent-Driven Codebase Rewrites: What Bun's Zig-to-Rust Port Teaches — codex.danielvaughan.com — 五阶段框架、验证堆栈、token 成本的技术拆解
  3. Bun 1.4: The controversial AI-Driven Rewrite from Zig to Rust — grigio.org — 社区反应、PORT NOTE 注释、性能与争议
  4. Bun's Zig-to-Rust Rewrite: Engineering Realities — dasroot.net — 工程动机、性能基准(14,120 req/s)、二进制缩减 3–8 MB
  5. Anthropic's Bun Rust rewrite merged at speed of AI — The Register — 主流媒体第一手报道,确认 PR #30412 与六天时间线

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!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 等场景全覆盖。

51学通信知识星球海报-扫码加入