Bun が Zig から Rust に書き直された本当の理由 — Anthropic 買収・Zig の AI 禁止・Claude による 6 日 96 万行ポート

(更新: 2026-07-03) by ZeroZawa

2026 年 5 月 14 日、Bun のメインリポジトリに 1 件の PR がマージされました。番号は #30412、タイトルは「Rewrite Bun in Rust」。変更ファイル 2,188、追加 100 万行超、削除 4,024 行という規模で、ブランチ名は claude/phase-a-port1。Bun 創設者 Jarred Sumner は PR 説明文で「memory safety のためのコンパイラ支援が手に入った」と動機を述べています1

しかしこの PR を「Rust の方が安全だから書き直しました」で終わらせると、本質を見誤ります。Anthropic による Bun 買収 (2025 年 12 月)、Zig の LLM 寄稿禁止ポリシー、Claude が大規模言語間ポートの実用域に到達したこと、この 3 つの構造的圧力が同時に交差した結果として PR #30412 は存在します。本記事は公式説明の裏側にあるその力学を読み解きます。

3 つの構造的圧力の交差図

PR #30412 が示す「事実」

裏側に進む前に、公式情報を確定させます。憶測との境界を引くためです。

規模

  • マージ日: 2026-05-14
  • 変更ファイル: 2,188
  • 追加: 1,009,257 行 / 削除: 4,024 行
  • コミット数: 6,755 (報道ベース)2
  • ブランチ名: claude/phase-a-port1

ブランチ名に claude が含まれている事実は記憶しておきたいところです。後で意味を持ちます。

性能

  • Linux x64 glibc で既存テストの 99.8% パス1
  • バイナリサイズ -3〜8MB1
  • ベンチマーク: 中立から高速1

「全プラットフォームで既存テスト通過、メモリリークと flaky テストもいくつか修正」が PR 説明文の中核です1。性能は劇的改善ではなく「中立から高速」と慎重な言い回しになっています。

PR #30412 の規模

2026-05-14 マージ・ブランチ claude/phase-a-port

0100,000200,000300,000400,000500,000600,000700,000800,000900,0001,000,000↑ 件数コミット削除行数変更ファイル追加行数指標
出典: GitHub PR #30412 / The Register (2026-05-14)。追加行数の桁が他指標を圧倒する非対称構造に注目

公式メッセージ

PR 説明文には 3 つの強調点があります1

  1. アーキテクチャとデータ構造は largely the same (大きく変えていない)
  2. 3rd party ライブラリは依然として少ない
  3. async Rust は使わない

つまり「Zig 版のホモロジーを保った Rust 版」であり、idiomatic Rust への作り直しではありません。Sumner の動機表現は「コンパイラ支援によるメモリバグ検出ツールが手に入った。これが何年もチームの開発・デバッグ時間を奪ってきた」というものです1

ここまでが公式情報です。なぜこれが起きたのかは、別の階層にあります。

第一の圧力 — Anthropic による Bun 買収

2025 年 12 月 2 日、Anthropic は Bun および開発チームを買収しました3。この事実が PR #30412 の出発点になります。

自社 AI を自社プロダクトへ

Anthropic は Claude Code を含む Claude シリーズを開発する企業であり、Bun を傘下に持つことで「自社 AI を自社プロダクト開発に投入する」整合性が一気に強化されました。Sumner は The Register に対して次のように述べています。

this is already the status quo; we haven’t been typing code ourselves for many months now2

「これはすでに現状で、ウチらはもう何ヶ月もコードを自分でタイプしていない」という発言は、買収後すぐに開発体制が AI 主導へ移行していたことを示唆します。Rust ポートの「6 日」は突然の試みではなく、すでに稼働している AI 主導開発の延長線上にあったと考えられます。

言語選定基準のシフト

買収によって何が変わったのでしょうか。言語選定の基準が「人間が書きやすい」から「AI が安全に書ける」へ重みづけが移った点です。Zig はチームが愛着を持って選んだ言語ですが、AI が大量に生成するコードに対するコンパイラの守りは Rust の方が強いといえます。借用検査と所有権による所有移転、ライフタイムによる use-after-free 検出、Drop による deterministic 解放が compile time に効きます。AI 生成コードに対するガードレールとして Rust の型システムは Zig より明確に厚くなっています。

組織の構造が変わると、最適な言語も変わります。これが第一の圧力です。

第二の圧力 — Zig の LLM 寄稿禁止

Zig コミュニティは LLM 生成コードの寄稿を upstream で受け入れない方針を表明しています。The Register の取材に対し Zig 側は「AI の側面を抜きにしても歓迎しない」と回答しました2

Bun の Zig fork 問題

Bun は debug compile time を 4 倍改善するパッチなどを Zig に対して持っており、これらは upstream できないため独自 fork を維持する状況にありました (報道ベース)4。AI 主導開発を本格化させた Anthropic 配下の Bun にとって、この fork コストは加速度的に膨らむと予測されます。

問題はパッチの量ではなく governance の構造的衝突です。人間が type しない開発体制と、AI 寄稿を受け入れない言語コミュニティ。両者は構造的に両立しません。Bun が Zig fork を続けるほど upstream との乖離は深まり、コミュニティの恩恵 (security fix / コンパイラ改善 / 周辺ツール) を受ける口は狭くなります。

v1.3.14 が「最後の Zig 版」

Sumner は「これが Zig 最後のバージョンになる」と述べ、v1.3.14 リリースを Zig コードベースの最終版と位置づけました2。技術スペックではなく governance 互換性によって言語選定が決まった事例として、PR #30412 はテックヒストリの教材になります。

第三の圧力 — Claude が大規模ポートの実用域に

ブランチ名 claude/phase-a-port の存在が、第三の圧力の核心です。Phase A という命名は、Claude が担当した工程が複数フェーズの最初のものであることを示唆します。Sumner も PR 説明文で「クリーンアップ作業は一連の follow-up PR で行う」と明言しています1

「6 日」の表向きと実態

Stork.AI の報道によれば、Rust リライトは 6 日間で既存テストの 99.8% パスを達成しました3。一方 Hacker News では sesm が次のように指摘しています。

rewrite took 1 week, I wonder how much time went into preparing this file with very detailed instructions on mapping Zig to Rust idioms5

「リライト自体は 1 週間だが、Zig→Rust のイディオム変換を指示する詳細ファイルを準備するのにどれだけ時間がかかったか想像がつかない」という指摘です。Sumner 自身も HN で「ドキュメント執筆と rewrite どちらが時間かかった?」と聞かれて「almost (ほぼ同等)」と答えています5

つまり「6 日」はコード生成フェーズの実時間であり、変換ガイド作成・反復実験・compile error の修正ループ・テスト検証を含めれば数ヶ月オーダーの工数が前段にあります。AI が一晩で 1M 行を吐いた、という物語ではありません。

ホモロジー戦略

logicprog は HN で次のように要約しています。

the port maintains structural homology to enable future safe refactoring rather than attempting immediate idiomatic Rust5

idiomatic Rust にいきなり翻訳するのではなく、Zig の構造をそのまま Rust に写像します。バグもそのまま持ち込む代わりに、Rust の compile error と test failure を一度だけ集中砲火で潰します。idiomatic 化は post-port の課題として後回しにします。これが大規模 AI ポートを 6 日に押し込めた設計判断の核心です。

つまり実用条件は次の 3 点に集約されます。

  1. 包括的テストスイート (回帰検出の信頼性)
  2. ホモロジー戦略 (idiomatic より忠実翻訳を優先)
  3. 事前準備の工数 (変換ガイド・反復・修正ループ)

影 — unsafe blocks 1万超えが示す限界(一次再計測)

公式動機は memory safety です。しかし PR #30412 マージ後の Rust コードベースには大量の unsafe ブロックが存在します。当初の執筆時点では Hacker News コメンターの gm678 の実測 (10,428 unsafe blocks across 736 files)5 と byteiota の報道 (13,000+ unsafe blocks across 681,000 lines)6 という他者実測の引用のみで構成していました。本節では PR #30412 の head コミットを実際に自分の手元へ clone し、独自に再計測した一次データへ更新します。

計測方法

対象は PR #30412 の head commit ed1a70f8 (refs/pull/30412/head、2026-05-14 付。記事が扱う変更内容そのもの) です。以下の手順で shallow clone を取得し、rg 14.1.0 で -t rust フィルタをかけて計測しました (計測日 2026-07-02)7

Terminal window
git clone --depth 1 --filter=blob:none https://github.com/oven-sh/bun bun-repo
git fetch --depth 1 https://github.com/oven-sh/bun.git ed1a70f81708d7d137de8de057d11668c5f4e220
git checkout -b pr30412-head FETCH_HEAD
rg -c 'unsafe\s*\{' -t rust # unsafe ブロック開始の行数をファイル別に集計

unsafe ブロック密度の比較 (1,000 行あたり)

Bun Rust 版は一次再計測ベースで uv の約 51 倍の密度

012345678910↑ 1,000 行あたり unsafe ブロック数Bun (Rust 版)uv (Astral)プロジェクト
出典: Bun は筆者による PR #30412 head (SHA ed1a70f8, 2026-05-14) 再計測 (rg 14.1.0, 2026-07-02: unsafe block 10,470 / 総 LOC 985,081)。uv は byteiota 記事からの引用値 (73 blocks / 350K 行、未検証の第三者データ)

実測結果

指標結果
unsafe ブロック開始 (該当行数 / 出現数)10,470 行 / 10,492 出現 (737 ファイル)
unsafe キーワード総出現数13,907
unsafe fn1,204
unsafe impl394
unsafe trait21
.rs ファイル総数1,448
総 LOC (wc -l 合計)985,081 (非空白行 901,414 / *_sys 系 FFI vendor crate 除外 938,079)

unsafe ブロック数が多いクレート上位は src/runtime (4,689)・src/jsc (712)・src/install (515)・src/bundler (477)・src/bun_core (363) でした。

gm678 との照合

gm678 の実測 (10,428 blocks / 736 files) と今回の一次再計測 (10,470〜10,492 blocks / 737 files) は、件数で 0.6% 未満・ファイル数で 1 件の差にとどまります。同じ PR head コミットに対する独立測定として、gm678 の数値と手法 (unsafe ブロック開始の文字列一致カウント) を強く裏付ける結果になりました。

byteiota の手法上の知見と未解決の乖離

byteiota の「13,000+ unsafe blocks」は、実際のブロック数 (10,470〜10,492) よりも unsafe キーワードの総出現数 (13,907: fn/impl/trait/block を合算した値) に近い値でした。byteiota の「unsafe blocks」という表現が、ブロック開始だけでなく unsafe fn / unsafe impl / unsafe trait を含む全キーワード出現を合算した集計である可能性を示唆します。ブロック単体のカウントとキーワード全体のカウントを混同した手法上の相違を、一次データで初めて文書化できました。

一方 byteiota の「681,000 行」は、今回計測した総 LOC (985,081 行 / 非空白 901,414 行 / FFI vendor crate 除外 938,079 行) のいずれとも一致しませんでした。試した範囲のフィルタでは再現できておらず、この乖離は未解決のまま記録しておきます。byteiota 側の集計対象や計測タイミングが異なる可能性はありますが、断定はできません。

なお uv (350,000 行 / 73 unsafe blocks) との比較は byteiota 記事からの引用であり、本セッションでは uv 側の再計測を行っていません。この数値は第三者データのままである点に注意してください。

unsafe の発生源

byteiota は主な発生箇所として 2 つを挙げています6

  1. JavaScriptCore (JSC) との FFI 境界呼び出し
  2. Zig 設計から温存された global mutable state (Rust の所有権モデルにきれいに乗らない)

JSC との FFI は Bun のアーキテクチャの根幹であり、ここを safe にするには Bun のコア設計を再検討する必要があります。global mutable state も同様で、ホモロジー戦略を選んだ時点で温存される宿命にありました。

「memory safety はゴールでなく出発点」

PR 説明文の動機表現を額面通り受けると「memory safety を達成した」と読みたくなりますが、unsafe 密度の現実を見れば memory safety は到達点ではなく出発点です。Rust の compile time チェックが効く部分はクリーンになりましたが、unsafe ブロックの 1 万件超 (一次再計測で 10,470〜10,492) は人間の audit 対象として残ります。Sumner が PR 説明文で「optimization 残」「cleanup 残」と明言したのも、この後続コストを示しています1

採用判断と AI コーディングへの含意

PR #30412 を「Rust になって速く・安全になった」で評価して採用判断を変えるのは早計です。

canary を本番に入れる前に

Sumner は試用方法として bun upgrade --canary を案内し、optimization と cleanup が残っていることを明言しています1。本番投入前に確認すべきは次の 3 点に絞られます。

  1. 自分のワークロードでベンチマーク結果が「中立から高速」のどちら寄りか実測
  2. JSC FFI 境界 (Worker / native addon / FFI) を多用する場合は memory leak の長時間負荷試験
  3. follow-up PR がリリースされる前提で、stable まで何回バージョンを跨ぐか確認

「Rust になったから即採用」ではありません。「Zig 版より stable まで時間がかかる可能性がある」と読むのが妥当です。

AI コーディング検討者への 3 教訓

PR #30412 は AI 主導大規模ポートの test case として読めます。導入を検討するチームへの教訓は以下に集約されます。

  • 包括的テストが前提: テストスイートが弱いと AI ポートは vibe porting (統計的には動くが理解の浅い翻訳) に陥ります5
  • ホモロジー戦略: 一度に idiomatic 化を狙わず、構造を保って翻訳し refactor を分離します
  • 後続コストの計上: ドキュメント執筆と rewrite が同等工数 (Sumner 証言)、unsafe 削減と最適化はマージ後の長期作業です

3 圧力の交差タイムライン (2025-12 〜 2026-05)

買収・Zig 政策・PR open・merge が 6 ヶ月窓に集約

1.01.52.02.53.03.54.0↑ 累積イベント数Jan2026FebMarAprMay日付 →
イベント順 → 1: Anthropic 買収 / 2: Zig が LLM 寄稿禁止表明 / 3: PR #30412 open / 4: PR #30412 merged。縦軸は累積イベント数

タイムラインで見ると、買収 (2025-12)・Zig 政策 (2026 年春)・PR open (2026-05-08)・merge (2026-05-14) は 6 ヶ月の窓に圧縮されています。3 つの圧力が同時に揃った結果としての必然性が時系列でも見えます。

まとめ

Bun の Rust リライトは単一の技術選定ではありません。Anthropic 買収による組織変化、Zig コミュニティの governance 摩擦、Claude が実用域に達した技術タイミング。この 3 つが 6 ヶ月の窓に同時集約した結果として PR #30412 は存在します。同じ条件 (自社 AI 保有 + governance 摩擦 + LLM 実用域) が揃えば、類似の動きは他プロジェクトでも起こりえます。

「Rust に書き直されたから安全になった」という表層の物語ではなく、3 圧力の交差として PR #30412 を読むこと。これが採用判断と AI コーディング検討の双方に効く読解の更新だと考えています。

参考文献

Footnotes

  1. Rewrite Bun in Rust by Jarred-Sumner · Pull Request #30412 · oven-sh/bun — PR 本文。規模・動機・canary 案内の一次ソース 2 3 4 5 6 7 8 9 10 11 12

  2. Anthropic’s Bun Rust rewrite merged at speed of AI - The Register — Sumner 直接引用 (we haven’t been typing code ourselves)・Zig 側コメント・性能数値 2 3 4

  3. Bun’s Rust Rewrite: An Analysis of the Zig vs. Rust Debate - Stork.AI — Anthropic 買収日 (2025-12-02)、6 日で 99.8% pass の出典 2

  4. AI Porting: Claude Rewrites Bun Codebase in Rust - heise online — Anthropic 買収 (2025 年末)、v1.3.14 が Zig 最終版、Bun の Zig fork 文脈

  5. Rewrite Bun in Rust has been merged | Hacker News — 691 points / 771 comments。gm678 の unsafe 実測 (10,428 / 736 files)、sesm の事前準備指摘、Sumner の応答 (“almost”)、logicprog のホモロジー戦略解説 2 3 4 5

  6. Bun Rust Rewrite Merged: The 13,000 Unsafe Block Problem - byteiota — uv との unsafe 密度比較 (350K 行 / 73 unsafe)、JSC FFI と global mutable state を unsafe 発生源として特定 (筆者は匿名マスコットのため数値は HN 実測と併記) 2

  7. 筆者による一次再計測。PR #30412 head commit ed1a70f81708d7d137de8de057d11668c5f4e220 (refs/pull/30412/head) を git clone --depth 1 --filter=blob:none で取得し、git fetch --depth 1 + git checkout -b pr30412-head FETCH_HEAD で pin。rg 14.1.0、-t rust フィルタで rg -c 'unsafe\s*\{' (ブロック開始) / rg -o '\bunsafe\b' (キーワード総数) / rg -o '\bunsafe fn\b' / \bunsafe impl\b' / \bunsafe trait\b' および wc -l を実行。計測日 2026-07-02。