智算多多
官方邮箱:service@zsdodo.com

公司地址:北京市丰台区南四环西路188号总部基地三区国联股份数字经济总部


京公网安备11010602202532号 Jarred Sumner 一直强调,这次迁移的动机并不是为了提升性能。
过去这些年里,Zig 代码库让团队花费了大量时间去调试内存相关问题,比如释放后使用、重复释放,以及各种常见的内存管理错误。而迁移到 Rust 的核心理由,是借助编译器提供的内存安全保障。
换句话说,把 Zig、C、C++ 等语言需要程序员自行保证正确性的那类问题,在编译阶段就直接发现并阻止。
这是一个合理且值得尊重的迁移动机。事实上,这也是许多大型系统项目转向 Rust 时最常提到的原因。
但是,这次重写后的代码中,我们发现分布在 700 多个文件里的 unsafe 代码块超过了一万个。
这是一个什么样的概念?简单说明一下,同样来自这一生态领域、体量也大致相当的 Rust 项目 uv,整个项目中只有 73 个 unsafe 块。所以这并不是数量级上的小差异,而是整整相差两个数量级。而这一结果,恰恰来自 Bun 团队所采用的迁移策略。
Bun 团队发布的迁移指南明确要求 Agent 尽可能忠实地移植 Zig 代码——保持相同的架构、相同的数据结构,逐文件进行转换。
但一个依赖手动内存管理的实现,在被“忠实移植”之后,并不会自动变成内存安全的代码。它只是变成了一份披着 Rust 外衣的手动内存管理实现。
每当原始 Zig 代码中的逻辑无法通过 Rust 借用检查器验证时,迁移过程就会使用 unsafe 来绕过限制。而借用检查器恰恰会在这些地方失去作用——也正是在这些地方,它原本最应该发挥价值。
开发者 Todd Smith 曾向我指出,其实事情未必一定会发展成这样。他们完全可以提前设置约束,例如明确规定“禁止使用 unsafe”,甚至通过 Git 的 pre-commit hook 在提交前强制检查。
在这样的限制下,一个足够优秀的大语言模型理论上会寻找其他实现方式,在迁移过程中逐步引入真正的内存安全机制。当然,即便如此,也仍然需要大量人工审查。而正如 Todd 所说的那样,这本身就已经构成了一个充分理由:不要轻易尝试这种迁移方式。
因此,99.8% 的测试通过率与超过 1 万个 unsafe 引用之间,其实并不存在任何矛盾。它们本质上是在描述同一件事。
测试通过率如此之高,是因为这次迁移足够忠实;unsafe 数量如此之多,同样也是因为这次迁移足够忠实。“忠实还原”是目标,而这个目标确实实现了。
但没有实现(也是这种“忠实迁移”本身无法实现)的是,那项原本被用来作为迁移动机的安全性承诺。
你可以得到一个忠实的移植版本,也可以得到一份符合 Rust 惯用写法、真正安全的 Rust 代码。前者是逐文件翻译的 LLM 最容易生成的结果;后者才是“内存安全”这一论点所承诺的东西。
这两者并不是同一个产物。而测试套件无法区分它们,因为从外部接口行为来看,两者完全等价;至于底层实现是否真正安全、内存是否得到可靠保障,仅靠行为测试是无法判断的。
最自然的辩护理由是:现在还只是早期阶段。这个版本目前只在 Canary 渠道发布,后续还有更多 PR。随着 Bun 团队逐步重构成符合 Rust 惯用写法的代码,unsafe 的数量自然会下降。
也许确实如此。但问题在于,我们需要诚实地面对一个事实:所谓“逐步消除 unsafe”,并不是简单的代码清理工作,而是一个尚未被彻底解决的研究难题。
验证 Rust 中一段 unsafe 代码是否真正安全,本身就是一件极其困难的事情。困难到什么程度呢?Amazon 曾联合 Rust 基金会发起专门的社区项目,目的就是验证 Rust 标准库中的 unsafe 代码。这部分代码远比数百万行由智能体生成的运行时代码规模小得多,也经过了更严格的审查,而且是由人工编写的。
之所以需要专门成立这样的项目,是因为 unsafe 代码重新打开了通往未定义行为的大门。只要某个 unsafe 代码块中存在一个错误,就可能让周围所有依赖 Rust 类型系统保护的代码失去保障。这一点,Todd Smith 很久以前就曾向我强调过。而对于任何使用 Rust 的开发者来说,这都是一个值得认真记住的警告。
事实上,即便是 Rust 标准库本身,在过去这些年里也出现过二十多个可以追溯到 unsafe 代码的 CVE 漏洞。尽管这些代码已经接受了数十年专家级别的审查,问题依然存在。
当前学术界在验证 unsafe Rust 方面最先进的方法,也不过是半自动化分析工具,以及需要人工编写形式化规范的实验性验证器。
不存在一个按下按钮就能完成的“让这段 unsafe 代码变得安全”的工具,而且在可预见的未来,也看不到这种工具出现的可能。
Todd 基于他长期研究类似问题而给出的建议是:“根本不要自动迁移内存不安全的代码。应该先为产品的外部可观察行为编写详细规范,然后告诉 Agent:现有代码只能作为参考资料,用来补充实现细节,而真正的主要依据应该是规范本身。”
当然,这又带来了另一个问题:你首先必须拥有一份完整、准确、足够详细的规范文档。
这意味着,从超过一万个 unsafe 代码块走向一个真正站得住脚、能够被证明安全的系统,并不是靠几个后续 PR 就能完成的事情。
那将是一场持续数年的审计工程。
更麻烦的是,这场审计面对的目标,是一个生成速度远远超过人类阅读速度的代码库。代码生成能力正在指数级扩张,而代码验证能力却没有。
这种不对称,才是真正值得关注的新闻。而且,这并不仅仅是 Bun 的问题。Bun 可能只是迄今为止规模最大、曝光度最高的案例而已。
在 Hacker News 的讨论中,最激烈的问题最终并不是 Bun 使用“Rust 还是 Zig”开发的,也不是“AI 是否应该编写运行时系统”。
大家最终聚焦的问题更加具体,也更难回避:一个智能体在九天内生成的一百万行代码,到底是谁审核的?
坦率地说,看起来并没有人以审查这种关键基础设施代码应有的方式去完整阅读它。
原因也很简单:按照代码生成的速度去阅读这些代码,本来就不是人类能够做到的事情。
Bun 团队目前的信心主要来自测试套件。
但这又回到了文章开头提到的问题:测试套件从来没有验证过这次迁移最核心的目标。
这一切并不意味着 Bun 一定会出问题、崩溃。它完全有可能在未来很多年里稳定运行。事实上,能够忠实移植一套已经正常工作的代码,本来就是“忠实移植”存在的意义。
那 0.2% 未通过测试的部分,大多是边缘场景和平台特定行为。而未定义行为从来不会通过测试失败主动暴露自己。
它更可能以另一种方式出现:比如 18 个月后,在某个 CI 环境里从未运行过的 libc 实现上,被发现并登记成一个 CVE 漏洞。又或者,是某家路由器厂商恰好选用了某个行为古怪的 musl 版本,然后问题才第一次浮出水面。
从明显可见的层面来看,这次重写并没有让 Bun 的风险状况比 Zig 版本更糟。但它也没有按照宣传时所承诺的那样,在“内存安全”这一特定维度上变得更好。
如今,一个拥有大量 unsafe 代码块的系统,已经成为支撑整个运行时的基础设施。而根据 Anthropic 自己的描述,这个运行时最终会被集成进 Claude Code,并服务数百万用户。
这个迁移得出的结论并不是:“AI 不行”。也不是:“Rust 不行”。
事实上,Rust 是优秀的语言。AI 也是优秀的工具——前提是像使用其他工具一样,以负责任的方式使用它。
真正值得吸取的,是一种评估和验证的思维方式。当有人拿测试通过率来证明某种安全属性时,你首先应该确认:
这个测试套件真的在测量那个属性吗?
行为一致性和内存安全性,是两个完全不同的维度。
一个全部通过的测试套件,只能说明:新实现的行为与旧实现一致。
如果旧实现本身是一套依赖手动内存管理的系统,而新实现只是对它进行了忠实翻译,那么测试全部变绿所证明的,仅仅是:迁移工作完成得很好。
除此之外,它完全无法告诉你:这套系统是否真正安全。
真正能够回答这个问题的指标,其实是大家最想看到、却至今没人能够给出的那个指标。
原因很简单:如何可靠地证明这一点,直到今天依然是一个尚未解决的难题。
而这,才是整个事件真正值得关注的地方。
