Bun(JSランタイム)がZigからRustへバイブポーティング中
(github.com/oven-sh)- Bunの創設者 Jarred Sumner が Zig → Rust ポーティングガイド(PORTING.md)を
claude/phase-a-portブランチにコミットし、AIエージェントを活用した大規模な言語移行実験が公開された - ポーティングは Phase A(ファイル単位でロジックだけを粗く翻訳、コンパイル不要)と Phase B(クレートごとにコンパイル通過)に分かれ、約300個の型・イディオム対応ルールを LLM に与える方式
- Sumner 本人が Hacker News で「リライトを確定したわけではなく、このコードは全部捨てられる可能性が高い」と述べており、現時点では実験的な探索段階
- コミュニティでは Anthropic 買収後の Zig の AI 貢献禁止ポリシーとの衝突、Bun がすでに Zig をフォークして運用している点、Rust エコシステムの安全性の利点などが背景として挙げられている
- PR の大半が @robobun(AIボット)によって自動生成され、CodeRabbitAI と Claude がレビューする構成で進められており、AI主導の大規模コードマイグレーションの現実的な可能性と限界を示す事例
ポーティングガイド(PORTING.md)の主要構造
- ポーティング対象は Zig ファイル 1 つを同一ディレクトリ内の
.rsファイルへ変換することで、Phase A では ロジックの忠実な再現が目標であり、コンパイル可否は問わない tokio,rayon,hyper,async-trait,std::fs,std::netなど 外部の非同期・I/O クレートの使用禁止 — Bun が独自のイベントループとシステムコールを所有しているためasync fn禁止、すべての非同期処理は Zig と同様に コールバック + 状態マシン方式を維持- 確信が持てない部分は
// TODO(port):、性能関連の Zig イディオムは// PERF(port):としてマークし、Phase B で処理
型・イディオム対応ルール
[]const u8→&[u8](絶対に&strではない)、?T→Option<T>、anyerror!T→Result<T, bun_core::Error>など 50個以上の型マッピング表を提供defer x.deinit()→ 削除後にimpl Dropへ置換、errdefer→scopeguard使用、comptime→ const generic・const fn・macro_rules!へ変換- 文字列は バイトベースで処理する原則:
std::string::Stringや&strの使用を禁止し、&[u8]/Vec<u8>を使用 — Bun が WTF-8 と任意バイトを扱うため @intCast→T::try_from(x).unwrap()(常に検査)、@truncate→x as T(意図的ラップ)、@bitCast→transmuteなど Zig 組み込み関数ごとの Rust 対応を整理
クレートマップと所有権モデル
@import("bun").Xなどの Zig 名前空間をbun_str,bun_sys,bun_jsc,bun_allocなど 約30個の Rust クレートに 1:1 マッピング- AST/パーサークレートは
bumpalo::Bumpアリーナを維持し、それ以外のクレートは グローバル mimalloc アロケータを使うことで allocator パラメータを削除 bun.ptr.Owned→Box<T>、bun.ptr.Shared→Rc<T>、bun.ptr.AtomicShared→Arc<T>などポインタ所有権のマッピング
コミュニティの反応(Lobsters・HN)
- **「本当に Rust へ移行しようとしているのか、それとも Anthropic LLM のショーケースなのか」**という疑問を呈する意見が多数
- Zig の AI貢献禁止ポリシーと Anthropic の AI中心開発ワークフローとの衝突が背景かもしれないという推測がある一方、陰謀論レベルだという自己評価も併存
- 約300個のルールを LLM が忠実に守れるのかについて懐疑的な見方 — 「約16kトークンならサブエージェントにはちょうどよい」という肯定的評価もある
- 「Phase A でコンパイルできないコードを先に作るアプローチが 従来のコーディングエージェントの使い方と正反対」という興味深い観察
- Bun の Zig フォーク維持負担、Zig の頻繁な 破壊的変更、まだベータ段階の言語に中核製品を依存するリスクなどが移行動機として言及されている
1件のコメント
Lobste.rsの意見
ちなみに、この件についてJarred SumnerがHNで述べていたことはこうだとのこと: Bunの開発者であり、これは自分のブランチで、このスレッドは動かないコードに対する過剰反応だという立場。
まだ書き直すと決めたわけではなく、このコードが丸ごと捨てられる可能性もかなり高いとのこと。
動くバージョンがどんな形になるのか、性能はどうか、Bunのテストスイートを通して保守可能にする難易度がどれほどかを見たいし、実現可能なRust版とZig版を並べて比較したい、という趣旨。
大衆文化的な技術解釈は、たいてい即時反応に依存しがちだ。
Bunの通常のプルリクエストもかなり混沌としている: https://github.com/oven-sh/bun/pulls?q=is%3Apr+
ほとんどは**@robobunが自律的に作成し、GitHub Actionsで重複の有無を確認し(Claudeベース)、@coderabbitai**と@claudeがレビューしている。
その一方でCIは壊れており、@robobunは自分が作った別のPRと重複しているという理由で、自分のPRの一部を結局閉じている。
mainへのマージはまだ人間がやっている。
BunはJarredの性能への執着で称賛されていた記憶があるが、コードベースでLLMがここまで暴れ回るのを許すとは思わなかった。
これはありえない。
「イディオム対応表」を見ると
unsafeだらけで、Rustらしくないコードが大量に出てきそうだ。@fieldParentPtr("field", ptr)の対応は特に粗っぽく見える。ただし「phase A」は実質的に行単位の翻訳で、その後のプロンプトでよりイディオマティックで保守しやすいRustへリファクタリングしようとしているようだ。
問題は、言語設計が実装の方向性を強く押し出しうるし実際そうなるので、あとから解きほぐしにくい絡まりが生じる可能性が高い点だ。
結局のところ、昔ながらの手作業による書き直しのほうが良い道だったのではないか。
特にAnthropicほどの資金力があれば、AIの便利な点は同じコードを何度でもリファクタリングしても疲れないことだ。
マイグレーションそのものとは別に、彼らが選んだやり方が特に興味深い。
リンク先の
docs/PORTING.mdにはポーティング規則が約300個あるが、どのLLMもこれを全部「記憶」して忠実に従うには多すぎるように見える。AnthropicがBunを所有しているので、このポーティングには事実上無限のトークン予算があるはずで、もしかすると
ファイル数 * 規則数の数だけエージェントを立ち上げて、すべて守られているか「保証」しようとしているのかもしれない。また、ポーティングを2段階に分けている: Aでは各ファイルを孤立した状態で粗くポートし、コンパイルは壊れると想定する。Bでは全体をつないでコンパイルできるようにする。
phase Aではエージェントにコードが「コンパイルできる必要はない」と伝え、各ポート済みファイルを出力品質に応じて低・中・高で採点させている。
低はロジックが間違っている、中はロジックは合っているがコンパイルできない、高はロジックも合っていてコンパイルも通りそう、という意味だ。
私が理解し実際に使っているコーディングエージェントのやり方とは正反対なので、結果が気になる。
私の感覚では、コンパイルできる必要がないとして明確な「終了目標」を与えないと結果はかなり予測不能になり、phase Bでは信頼できないコードの山をレビューする羽目になりそうだ。
ざっとgrepしてみたところ、この出力品質スコア1279件のうち約3%が低、80%が中、17%が高だった。
PORTING.mdは約16kトークンで、主要な作業に集中している。新しいサブエージェントに渡すには悪くなく、むしろ理想的かもしれない。
実際にRust移行を望んでいるのか、それともAnthropicのLLM実験なのか気になる。
AnthropicがZigで最も人気のあるプロジェクトの一つであるBunを別の言語へ移すなら、かなり露骨な力の誇示になる。
もちろんこのドラマ的な仮説を完全に信じているわけではなく、単にAnthropicの潤沢な資金で製品デモをしたいだけかもしれない。
かなり興味深そうだ。
一度に処理しなければならない規則の束は、膨大なコードレビューのサイクルを経なければ検証不可能に見える。
トークンは多いだろうが、こうした変換のあとではコードを事実上検証するのが非常に難しくなりそうだ。
テストも同じ過程を経る必要があるなら、結局真実の基準として何が残るのか疑問だ。
それでも実験としてはすごい。
Node.jsキラーたちのその後を見ると、Denoは権限システムやTypeScript標準サポートのような小さな改善は提供したが、世界を揺るがすには至らず、こうした機能もNode.jsへ逆輸入されつつある。
使ってみた限りでは開発者体験が有意に良いとは感じず、pnpmのような優れたツールのせいでむしろ悪い場面もあった。
速い可能性はあるが、この5〜6年、自分の用途ではNode.jsの性能問題を特に感じたことはない。
JSRも世界を変えられず、コミュニティは代わりに、今ではより良い体験を提供するnpmxを作った。
ただ、Denoの標準ライブラリ、たとえば
@std/collectionsはかなり良くて使っている。Bunは範囲が広すぎて最初から危険信号が多かったが、Jarredが何年かけてでも最高の万能JSランタイムを作ろうとしているように見えたので、慎重ながら楽観していた。
しかしAnthropicに買収され、Jarredが今やかなり多くの~~バイブコーディング~~エージェント的開発をしている様子、さらに今回のバイブポーティングの話まで見ると、たとえ実験ブランチだとしても自分が使うプロジェクトではないという判断が固まった。
だからNode.jsが依然として支配的なのだ。
真面目な話、組み込みTypeScript機能とSQLiteはすばらしい。
完全な反AIというわけではなく、とても特定の問題を解くために小さなPythonスクリプトやWebアプリをバイブコーディングするのは面白いし有用だと思う。
だが、多くの可動部分とユーザーを抱える複雑なプロジェクトにおける大規模な「エージェント的開発」は、機能開発を一時的に速くしても、結局はプロジェクトを不安定にし肥大化させる純損失だという確信が何度も強まっている。
VSCode、Cursor、mise、PerplexityのWeb UIなどが思い浮かぶ。
スクロール時にもたつかないJSのドロップダウンを一つ作るのは、そんなに難しいことなのだろうか。
自分が依存する、より多くの大きなツール・ライブラリ・プロジェクトがこれに気づいて、より厳格な反AI方針を採用してほしい。
Nodeをより良くする圧力になったからだ。
Nodeは昔、わざとbtoaを実装しないほどだった。
だが結局、両方とも脚注として残ることになりそうだ。
文字どおり間違った方向だ。
中規模、つまり数十万行以上のRustプロジェクトを保守しながら、大規模コードベースでのスケーラビリティに満足しているRustメンテナを一人も見たことがない。
Rustは大規模コードベースに対して特に優れていると思う:
https://matklad.github.io/2023/03/28/rust-is-a-scalable-language.html
https://ferrous-systems.com/blog/rust-as-productive-as-kotlin/
ただし効率的に扱うには、ある程度自分が何をしているか分かっている必要がある:
https://matklad.github.io/2021/09/05/Rust100k.html
この文脈でZigがRustと比べてどうかはよく分からない。
TigerBeetleは設計の仕方がかなり特殊だ。
また、2万行のRustプログラムが30万行のGoプログラムの中核機能を実装した事例もいくつか知っている。
なので、厳密にはあなたが言った条件とは違う。
それでも1万〜10万行の範囲では、保守者としてRustに非常に満足している。
この程度の規模は、プログラムが十分に集中していられるほど小さく、それでいて一つの中核アイデアをしっかり実装するには十分大きい。
この規模では言語そのものもツールも大きな資産だった。少なくとも私の個人的経験ではそうだ。
cargo-nextestは現在、コメントと空行を除いてRustコード84k行あり、単独メンテナとして、自分の個人的な品質基準に見合うものを他の言語で書けるとは思えない。おそらくこれが理由かもしれない: https://github.com/oven-sh/bun/issues/28001
これは時間的メモリ安全性の問題ではない。