spec: function type inference should work in all assignment contexts
要約
概要
Go言語の関数型推論(function type inference)を、すべての「代入コンテキスト(assignment context)」に対して一貫して機能させるための仕様変更提案です。現状では、通常の代入文ではジェネリック関数の型推論が動作するにもかかわらず、複合リテラル内の要素代入やチャネル送信では明示的な型引数指定が必要という不整合が存在していました。
ステータス変更
likely_accept → accepted
2026年3月18日のProposal Review Meetingにて、前週からの議論に変更なしとして正式承認されました。仕様変更の具体的な文言がCL 751312にまとめられており、コアチームの合意が形成されていたことが決定の背景にあります。
技術的背景
現状の問題点
Go 1.21でジェネリック関数の型推論が大幅に強化されましたが、型推論が動作する文脈と動作しない文脈に一貫性がありませんでした。具体的には、LHS(左辺)の型が完全に判明しているにもかかわらず、コンパイラが型引数を推論しないケースが存在しました。
type S struct{ f func(int) }
func g[T any](T) {}
func _(s S) {
s.f = g // ok: 通常の代入では型推論が機能する
s = S{f: g} // error: 複合リテラル内では推論されない
s = S{f: g[int]} // ok: 明示的な型引数指定が必要
}
同様の問題は配列・スライス・マップの複合リテラルおよびチャネル送信でも発生していました。
type F func(int)
type S []F
func g[T any](T) {}
func _() {
var s S
s[0] = g // ok
s = S{g} // error: 明示的指定が必要
var c chan F
c <- g // error: チャネル送信でも推論されない
}
提案された解決策
「代入コンテキスト」という統一的な概念を導入するのではなく、既存のassignability(代入可能性) の定義に新たなルールを追加するアプローチが採用されました。
Goの仕様における代入可能性のルール一覧に以下のケースを追加します。
ジェネリック関数
x(部分的にインスタンス化されている場合も含む)は、関数型Tに代入可能である。ただし、欠けている型引数がTから一意に推論できる場合に限る。
この変更により、代入可能性が判定されるすべての文脈(複合リテラル要素、チャネル送信、関数引数、return文、変換式など)で自動的に型推論が機能するようになります。
これによって何ができるようになるか
コード例
type Handler func(int)
type M map[string]Handler
func process[T any](T) {}
// Before: 明示的な型引数指定が必要
m := M{
"a": process[int],
"b": process[int],
}
// After: 型推論により省略可能
m := M{
"a": process,
"b": process,
}
type F func(string)
type C chan F
func handle[T any](T) {}
// Before: チャネル送信時に型引数が必要
var c C
c <- handle[string]
// After: 型推論が機能する
c <- handle
実践的なメリットとして次のような場面が挙げられます。
- ディスパッチテーブルの構築: 関数型のマップやスライスにジェネリック関数を登録する際、型引数の繰り返し記述が不要になる
- イベントシステムの設計: チャネルベースのイベントディスパッチにジェネリックハンドラを直接使用できる
- 構造体の初期化: 関数型フィールドを持つ構造体の複合リテラル初期化が簡潔になる
議論のハイライト
- バグか機能追加か: 当初はバグとして報告されたが、仕様書のInstantiationsセクションが型推論の適用範囲を明示的に限定しているため、仕様変更(言語プロポーザル)として扱われることになった
- 実装方針の転換: 「代入コンテキスト」という新概念を仕様に導入する案が検討されたが、最終的にはより既存の概念を活用した「代入可能性の定義拡張」というアプローチに落ち着いた。これにより、代入可能性が使われるすべての箇所で自動的にカバーされる
- go/types APIへの波及:
go/typesAPIにこの概念を統一的に公開することの有用性も議論された(関連: Issue #70638) - 変換式も対象: griesemerが指摘したように、変換式
T(x)におけるxも「代入コンテキスト」であるため、このケースも推論の対象となる - Issue #70638の実装促進: @adonovanの指摘により、この変更の受け入れが既承認の別提案(#70638: go/types の暗黙的変換情報の追加)の実装を促進する可能性がある