メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#79427active

decouple export data formats used by compiler and x/tools

新規提案

要約

AIによる要約であり、誤りを含む場合があります。

概要

コンパイラ(cmd/compile)とツール群(x/tools)が共有するエクスポートデータのフォーマットを分離し、それぞれが独立して進化できるようにするproposalです。現在の密結合な構造を解消し、Go言語の新機能追加プロセスを簡素化することを目的としています。

ステータス変更

(新規)active
2026年5月27日の週次Proposal Review Meeting(@adonovan, @bradfitz, @cherrymui, @griesemer, @ianlancetaylor, @neild, @rolandshoemaker 出席)にて、active列に追加され、週次レビューの対象となりました。@griesemerが「良いアイデアだが、ツール側への影響の把握が必要」とコメントしており、影響調査のための実験を提案しています。

技術的背景

現状の問題点

Goのエクスポートデータ(export data)とは、コンパイル時にパッケージ間で型情報を共有するためのバイナリ形式のシリアライズデータです。現在、2つの異なるフォーマットが存在します。

  • unified形式(u形式): cmd/compileが読み書きする形式。インライン展開やジェネリクスに対応した現行フォーマット。
  • indexed形式(i形式): x/tools(gopls等)が読み書きする旧来のフォーマット。
    問題は、go list -export コマンドがコンパイラを呼び出してエクスポートデータファイルを生成するため、x/toolsのリーダーがu形式も読めなければならない点にあります。この結果、コンパイラとx/toolsの間に複雑な依存関係が生じており、どちらかのフォーマットを変更すると両方のコードを更新しなければなりません。
    特に、Go言語に新機能を追加する際の手順が複雑になっています。例えばジェネリクスやエイリアス型パラメータの追加時に、std(標準ライブラリ)とx/toolsの間での版ずれ(version skew)への対処が求められ、開発の難易度が上がっていました。

提案された解決策

提案者(@adonovan、@cherrymui のアイデア)は以下の分離策を提示しています。
コンパイラ側(cmd/compile):

  • u形式のみを読み書きする
  • 同一バージョンのツールチェーンでのみ読み書き可能とし、形式を内部実装の詳細として扱う
  • 外部からの読み取りサポートを不要とし、自由に進化させる
    ツール側(x/tools):
  • i形式のみを読み書きする
  • go list -export が呼び出すバックエンドを、cmd/compileから新しい cmd/export ツールに切り替える
  • cmd/export は go/ast + go/types + vendor/x/tools を基盤とし、Goソースを解析・型検査してi形式のエクスポートデータを出力するシンプルなフロントエンドツール
    cmd/exportは関数本体の型検査が不要なため(go/typesがそのモードをサポート済み)、実際のコンパイラより大幅に高速に動作すると見込まれています。

これによって何ができるようになるか

この分離により、Go言語の新機能追加プロセスが以下のように整理されます。

  1. go/types に対応を追加 → 単一パッケージのテストが可能に
  2. コンパイラとそのエクスポートデータリーダー/ライターに対応を追加 → 複数パッケージのコンパイラテストが可能に
  3. x/toolsのリーダー/ライターに対応を追加
  4. x/toolsをGOROOTにvendoring → go list -export が新フォーマットを出力
  5. Goリリース
    コンパイラとツールが独立したフォーマットを持つことで、コンパイラ側は毎日自由にフォーマットを変更でき、x/tools側はi形式のみに集中できます。

コード例

// Before: x/toolsのReaderがコンパイラのu形式も理解する必要がある
// go list -export はcmd/compileを実行し、u形式のエクスポートデータを生成
// gcexportdata.Read() はu形式・i形式の両方に対応しなければならない
pkg, err := gcexportdata.Read(exportFile, fset, imports, path)
// After: 分離後の構造
// go list -export は新しいcmd/exportツールを実行し、i形式のエクスポートデータを生成
// gcexportdata.Read() はi形式のみに対応すればよい
pkg, err := gcexportdata.Read(exportFile, fset, imports, path)
// APIは変わらないが、内部実装が簡素化される

議論のハイライト

  • 影響調査の必要性: @griesemerは実験的にコンパイラのエクスポートデータを「毒入り(poison)」にして、ツール側で何が壊れるかを確認することを提案しています。go/importerパッケージが.aファイルを直接読む用途(go list -json経由等)への影響が未知数であり、調査が必要とされています。
  • 後方互換性について議論: 複数の関係者から「x/toolsのフォーマット後方互換性を保証できないか」という声があがりましたが、新言語機能が低レベルのパッケージに広く採用された場合、バージョンずれエラーを遅延させても実益が少ないと整理されています。
  • gccgoサポートの終了: @adonovanはこの議論と関連して、ジェネリクスをサポートしないまま実質停止しているgccgoのサポートを廃止するproposal(#79453)を別途提出しました。
  • 関連proposal #69491との連携: go/types自体にImport/Export関数を追加するproposal(#69491)と関連しており、これら一連の取り組みによってエクスポートデータの管理が整理される方向性にあります。
  • cmd/exportツールの軽量性: 関数本体の型検査が不要なため、cmd/compileより大幅に高速になる見込みで、クリティカルパスも短くなるとされています。

関連リンク