go/types: add StrictlyComparable function
要約
概要
go/typesパッケージに、ある型が「厳密に比較可能(strictly comparable)」かどうかを判定するStrictlyComparable関数を追加する提案です。ジェネリクスのcomparable制約を満たせるかどうかをAPI解析ツールから検査できるようにすることが目的です。
ステータス変更
active → likely_accept
2026年8月20日にactiveカラムに追加され、2026年9月9日の週次proposal reviewミーティングで、これまでの議論内容(トリビアルな追加であり、Go言語仕様に既に存在する概念をgo/typesで公開するだけという評価)を踏まえ、@aclementsにより「likely accept(最終確認期間に入る)」と判定されました。反対意見はなく、コアチームメンバー(@ianlancetaylor, @findleyr, @adonovan, @griesemer)もおおむね賛同しています。
技術的背景
現状の問題点
Go言語の仕様上、比較可能性には2種類の概念があります。
- spec-comparable(仕様上の比較可能性):
==演算子が使える型(インターフェース型も含む)。go/typesには既にComparable関数がありこれを判定できます。 - strictly comparable(厳密な比較可能性): ジェネリクスの
comparable制約を満たせる型(インターフェース型は原則含まれない)。
現在、後者を判定する公開APIが存在しません。そのため、エクスポートされた型Tが非公開フィールドの変更によって「厳密に比較可能」でなくなり、他所でcomparable型引数として使えなくなるような、後方互換性を壊す変更を検出できませんでした(例:cmd/apiのAPIチェッカーがこの種の破壊的変更を見逃す、Issue #56773)。
提案された解決策
go/types/predicates.go内部で既に使われているcomparableType(T, dynamic, seen)関数(dynamic引数で仕様上の比較可能性か厳密な比較可能性かを切り替えられる)をラップし、以下の関数を新規追加します。
// 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
}
これによって何ができるようになるか
go vetやgolang.org/x/tools/cmd/apidiff、cmd/apiのようなAPI互換性検査ツールが、「エクスポートされた型がcomparable制約を満たせるかどうか」をAPIの一部として静的に検証できるようになります。これにより、非公開フィールドの変更のみで意図せず型のcomparable満たし性が失われるという、検出が難しい後方互換性の破壊を機械的に検出できるようになります。
コード例
// Before: 厳密な比較可能性を判定する公開APIが存在しない
// go/types.Comparable は「仕様上の比較可能性」しか判定できない
ok := types.Comparable(T) // インターフェース型でも true になりうる
// After: comparable 制約を満たせるかを直接判定できる
ok := types.StrictlyComparable(T) // インターフェース型なら通常 false
apidiffのような互換性チェックツールでの利用イメージ:
// 旧バージョンの型 T が StrictlyComparable だったのに
// 新バージョンで false になった場合、破壊的変更として報告する
if oldOK && !newOK {
report("T is no longer strictly comparable: breaking change for comparable type params")
}
議論のハイライト
- 提案者は元々 Issue #56773(
cmd/apiが比較可能性の変化を検出すべき)の副産物として、go/typesにこの判定を公開APIとして持たせることを提案しました。 - @findleyr は「仕様に登場する型述語は原則すべてサポートすべき」として賛同しています。
- @kwjw は
apidiff側でこの関数を使って互換性チェックを実装する意欲を示しており、実際の利用先が明確です。 - @atdiar からは、そもそも
comparableの意味論(制約充足モードとインターフェース実装モードでの意味の違い)自体を仕様レベルで見直すべきではという、より根本的な議論も提起されましたが、これは本proposal(go/typesへのAPI追加)とは直交する話であり、本proposalの承認を妨げるものではないと整理されました。 - 実装自体は既存の内部関数
comparableTypeを引数falseで呼び出すだけの、非常にシンプルなラッパー追加であるため、大きな設計論争にはならず、レビューは比較的スムーズに進みました。