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

Go Proposal Weekly Digest

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

#72059active

go/types: add StrictlyComparable function

新規提案

要約

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

概要

go/typesパッケージに、ある型が「厳密に比較可能(strictly comparable)」かどうかを判定するStrictlyComparable関数を新設するproposalです。ジェネリクスのcomparable制約を満たすかどうかを、静的解析ツールから正確に検査できるようにすることが目的です。

ステータス変更

**(新規)active
2025年3月に提案されて以降、コアチーム(@findleyr, @griesemer, @adonovan)から明確な反対はなく「追加すべき」との合意が形成されていました。長らく@griesemerの休暇明けのレビュー待ちで滞留していましたが、2026年8月19日の週次proposal reviewでキュー入りが確認され、審査対象として「active」列に追加されました。今後、毎週のproposal reviewミーティングで正式な議論・決定が行われます。

技術的背景

現状の問題点

Go 1.18で導入されたジェネリクスのcomparable制約は、「spec-comparable(==が使えるが実行時にpanicし得る、interfaceを含む型も含む)」ではなく、「strictly comparable(実行時にpanicしない、真に安全に比較可能な型)」の集合を表します。しかしgo/typesが公開しているのはtypes.Comparableのみで、これはspec-comparable(弱い意味での比較可能性)しか判定できず、comparable制約を満たすかどうか(strictly comparable)を外部から正確に判定する手段がありません。
これにより、たとえばcmd/apiのようなAPI互換性チェッカーが「非公開フィールドの追加によって、エクスポートされた型がstrictly comparableでなくなった」という後方互換性を壊す変更を検知できません(関連issue #56773)。

type T struct {
    // すべてstrictly comparableなフィールド
}
// 後からこっそり以下のフィールドを追加すると、
// APIの見た目は変わらないのに T は comparable 制約を満たさなくなる
type T struct {
    unexported any // strictly comparableではない
}

提案された解決策

go/typesの内部関数comparableTypeを利用し、以下のシグネチャの公開関数を追加します。

// 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
}

内部では既存のcomparableTypeの第2引数(spec-comparableかstrictly comparableかを切り替えるフラグ)にfalseを渡すだけの薄いラッパーで、実装コスト自体は小さいものです。

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

  • API互換性チェッカーの強化: apidiffや将来のcmd/apiが、型のstrictly comparable性の変化を後方互換性を破壊する変更として検出できるようになります。
  • 静的解析ツールの高度化: go/analysisベースのlinterやコード生成ツールが、型がcomparable制約を満たすかを正確に判定できます。
  • ジェネリックコードのドキュメント/検証: ライブラリ作者が、公開型が意図せずstrictly comparableでなくなっていないかをCIで検証できます。

コード例

// Before: types.Comparable では spec-comparable しか判定できず、
// comparable 制約(strictly comparable)を満たすかは判定不能
ok := types.Comparable(T) // interfaceを含む型でも true になりうる
// After: comparable制約(ジェネリクス)の要件を正確に判定できる
ok := types.StrictlyComparable(T) // interfaceを含む型は false

議論のハイライト

  • #56773(cmd/apiでの比較可能性変化の検知)が本proposalの主な動機であり、kwjw氏はapidiffへの組み込みも検討していると発言しています。
  • findleyrは「原則として、spec中に現れる任意の型述語はgo/typesでサポートすべき」と述べ、追加に賛同しています。
  • atdiarは、comparableの意味が「制約充足モード(比較演算子を持つ)」と「interface実装モード(strictly comparable)」で二重の意味を持つ現状のspec設計自体に疑問を呈し、将来的な言語仕様の整理によってStrictlyComparable自体が不要になる可能性を示唆しつつも、「go/typesへの追加自体は言語仕様に依存せずバックエンド的に問題ない」として本提案には反対していません。
  • adonovangriesemerにレビューを一任し、彼が異議なければ次回のproposal reviewで前進させる方針を示しました。griesemerは「おそらく追加すべき」とし、reviewキューに追加。
  • 提案自体は非常に小規模(既存の内部ヘルパー関数の薄いラッパー)であるため、技術的な反対意見は見られず、主な遅延要因はレビュー担当者のスケジュールでした。

関連リンク