go/types: add StrictlyComparable function
要約
概要
go/typesパッケージに、ある型が「厳密に比較可能(strictly comparable)」かどうかを判定するStrictlyComparable関数を追加するproposalです。API互換性チェッカーなどのツールが、型のcomparable性という「隠れたAPI契約」の破壊的変更を検知できるようにすることが目的です。
ステータス変更
likely_accept → accepted
2026年9月9日の提案レビュー会議で「likely accept」と判定された後、2週間の最終確認期間を経て2026年9月16日の会議で「no change in consensus(反対意見の変化なし)」として正式にacceptedとなりました。GoチームのAPI互換性ツール(apidiffやcmd/api)の開発者からの支持もあり、大きな異論なく承認に至りました。
なお、承認後の9月22日に@griesemer氏から「既存のtypes.Comparableを使い、型引数を持つ型パラメータを構築すれば同等の判定が可能なので、このproposal自体が不要ではないか」という技術的な指摘がコメントされており、実装段階で議論が再燃する可能性があります。
技術的背景
現状の問題点
Go genericsにおけるcomparable制約は、「spec上の比較可能性(==が使える)」と「厳密な比較可能性(comparable制約を満たす、interfaceを含まない比較可能性)」という2つの異なる概念を内包しています。たとえば以下のように、エクスポートされた構造体Tは表面上のAPIを変えずに厳密比較可能性を失わせることができます。
// 変更前: Tは厳密に比較可能
type T struct {
/* エクスポート/非エクスポートフィールドは全て厳密比較可能 */
}
// 変更後: 非公開フィールドを追加しただけだが、Tは厳密比較可能でなくなる
type T struct {
/* ... */
unexported any // interfaceを含むため厳密比較可能ではない
}
これは公開APIのシグネチャ上は変化がないため、apidiffのような既存の互換性チェッカーでは検出できません。go/typesには spec-comparability を判定するtypes.Comparableはあるものの、厳密比較可能性を直接判定する公開APIが存在しませんでした。
提案された解決策
go/typesパッケージ内部に既にあるcomparableType関数(第2引数strictで挙動を切り替えられる)を利用し、以下のシンプルな関数を追加します。
// StrictlyComparable reports whether values of type T are strictly comparable
// (https://go.dev/ref/spec#Comparison_operators).
func StrictlyComparable(T Type) bool {
return comparableType(T, false, nil, nil) == nil
}
内部実装は既存であり、公開関数として薄くラップするだけの変更のため、実装コストは非常に小さいproposalです。
これによって何ができるようになるか
主な受益者はapidiffやcmd/apiといったGoのAPI互換性チェックツールです。これらのツールが型定義の変更を静的解析する際、StrictlyComparableを使えば「エクスポートされた型が厳密比較可能性を失っていないか」を機械的に検証できるようになり、ライブラリ作者が意図せず破壊的変更を混入させるのを防げます。
コード例
// Before: types.Comparable では spec-comparability しか判定できず、
// 厳密比較可能性を調べるには非公開関数 comparableType に頼るしかなかった
ok := types.Comparable(T) // strict/spec の区別ができない
// After: 厳密比較可能性を直接判定できる
if !types.StrictlyComparable(T) {
// T は comparable 制約の型引数として使えなくなった
// → apidiff 等が破壊的変更として報告可能に
}
議論のハイライト
- 提案の発端は#56773(
cmd/apiがcomparability変化を検出すべきという課題)で、非公開フィールド追加だけで厳密比較可能性が失われる問題が指摘されていた。 apidiffのメンテナ陣(@kwjw氏、@jba氏)から実用上のニーズが明確に示され、実装後はapidiffへの組み込みも計画されている。- @findleyr氏は「spec上に現れる型述語は原則としてgo/typesでサポートすべき」という一般原則を述べ、賛成を表明した。
- @atdiar氏からは、そもそも
comparable制約の意味論(制約充足 vs 制約実装)を整理すべきという、より広範な言語設計上の議論が提起されたが、本proposal自体(go/types向けの単純な追加)への異論ではないとされた。 - 承認後に@griesemer氏から、既存の
types.Comparableと型パラメータの構築を組み合わせれば同等の判定が可能であり、本proposalは不要かもしれないという指摘が出ており、実装フェーズでの扱いが今後の焦点となる可能性がある。 reflectパッケージへの同様の関数追加を求める声もあったが、@ianlancetaylor氏により「それは別のproposalとして扱うべき」と整理された。