spec: document that certain composite types have a fixed (but unspecified) size independent of composition
要約
概要
Go言語仕様において、スライス・ポインタ・関数・非空インターフェース・マップ・チャネルの各型のサイズは、その型の具体的な構成要素に依存せず常に一定(ただし未規定)であることを明文化する提案です。これにより、これまでコンパイラが拒否していた一部の再帰的型定義が正しく型検査できるようになります。
ステータス変更
(なし) → active
2026年7月1日、@griesemer(gri)が「議論の余地がほとんどない(uncontroversial)」として、この提案を通常の提案審査委員会(regular proposal committee)に移行させました。その後、@randall77・@adonovanから空インターフェースに関する懸念が示され、@griesemer が仕様文言に「non-empty」の限定を加える修正案を提示。これを受けて2026年8月19日の週次レビュー会議で議事録に記録され、8月20日に@aclements(proposal review group)によって正式にactiveカラムへ追加されました。今後は毎週のproposalレビュー会議で継続的に審議される段階に入ります。
技術的背景
現状の問題点
現在のGo仕様は、構造体や配列など「可変長」の複合型についてはサイズが定数であることのみを述べていますが、スライス・ポインタ・関数・インターフェース・マップ・チャネルといった「実装上は常に固定長」の型について、そのサイズが構成要素に依存しないことを明文的には規定していません。そのため、コンパイラはたとえば以下のような自己参照型を安全に扱えるにもかかわらず、型検査の段階で拒否してしまいます。
type A *[unsafe.Sizeof(A{})]byte // ERROR invalid recursive type: A refers to itself
A はポインタ型であり、ポインタのサイズはプラットフォームごとに固定(例えば64bit環境なら8バイト)であるため、unsafe.Sizeof(A{}) の値は本来 A 自身の定義に依存しません。しかし仕様上その保証が明示されていないため、コンパイラは循環参照とみなしエラーにしています。
提案された解決策
仕様に次のような一文を追加します(@griesemerの修正案)。
The sizes of slice, pointer, function, non-empty interface, map, and channel types are fixed, implementation-dependent constants specific to the kind of type but independent of the specific composition of the type.
空インターフェース(interface{})は自己参照ができないため対象から除外されています。これは「言語仕様の変更」ではなく、既存の実装事実を仕様として明文化(codify)するものであり、コンパイラの挙動自体は変わりません。
これによって何ができるようになるか
この明文化により、型チェッカーは「ポインタ・スライス・関数・マップ・チャネル・非空インターフェースのサイズは常に一定」という前提を型の循環検出ロジックに組み込めるようになります。実用上の恩恵はやや限定的で、提案者自身も「実際のプログラムへの利益はマージナル」「例は多分に技巧的」と述べていますが、unsafe.Sizeof を使った自己参照的な型定義や、ジェネリクスを用いたメタプログラミングのようなエッジケースで、これまで不必要にコンパイルエラーとなっていたコードが通るようになる可能性があります。
コード例
// Before: 現在の仕様では循環参照とみなされエラーになる
type A *[unsafe.Sizeof(A{})]byte
// invalid recursive type: A refers to itself
// After: 提案が採用されれば、ポインタのサイズが型の構成に依存しない
// ことが仕様上保証されるため、循環ではないと判定されコンパイルが通る
type A *[unsafe.Sizeof(A{})]byte // OK
議論のハイライト
- @griesemerは当初「議論の余地がない」としてスムーズな提案委員会移行を提案したが、その後 @randall77 が「将来的に空インターフェースと非空インターフェースでサイズを変える(例: 2ワード vs 3ワード)可能性がある」と懸念を表明。
- @adonovanはこの議論を追認しつつ、「3ワードのインターフェースはメモリ効率上望ましくなく、既存のアセンブリコードを壊すため現実的ではない」とコメントし、将来的な変更可能性は低いと示唆。
- 妥協案として、仕様文言に「non-empty」という限定を加え、空インターフェースを対象外とすることで決着。空インターフェースは自己参照できない性質上、この除外があっても本提案の目的(循環型検出の改善)は損なわれない。
- 関連issue #40169(
sizeofパッケージへのポインタ的型定数追加)や #77342(unsafe.Sizeofの引数評価の明確化)とも関連が深く、Go言語における「サイズ」の扱いに関する一連の仕様整理の一環と位置づけられる。 - 本提案は言語の挙動を変えるものではなく、既存実装の事実を仕様書に明記する「codification」であるため、後方互換性への影響はない。
関連リンク
- Proposal Issue github.com/golang/go
- Review Comment proposal review meeting
- Review Minutes (2026-08-19)
- 関連Issue #40169: sizeof: add synthetic, pointer-like types
- 関連Issue #77342: spec: clarify whether arguments of unsafe.Sizeof are evaluated
- 関連Issue #5069: spec: Document rules for recursive type and other self-referential decls (closed)
- Proposal Issue #79810