go/types: add TypeAndValue.IsConstant
要約
概要
go/types パッケージの TypeAndValue 型に、式が定数かどうかを判定する IsConstant() メソッドを追加する提案です。中身は tv.Value != nil と同じですが、名前で意図が読み取れるようにすることが目的です。
ステータス変更
(新規) → active
2025年4月にJonathan Amsterdam(@jba)氏が提出し、2026年11月12日に @aclements がproposal review groupを代表してactive列に追加しました。今後は週次のProposal Review Meetingで審議されます。現時点で設計上の議論は行われておらず、active入りの理由も明示されていません。変更は小さく後方互換性もあるため、優先度の高い提案の審議が一段落したところで順番が回ってきた可能性があります。
技術的背景
現状の問題点
types.TypeAndValue は型チェッカー(types.Info.Types)が式ごとに記録する情報で、式の型(Type)と、定数式の場合の値(Value constant.Value)を持ちます。式の種類を調べるために IsVoid、IsType、IsBuiltin、IsValue、IsNil、Addressable、Assignable、HasOk といった述語メソッドが用意されています。
ところが、「この式は定数か」を判定するメソッドはありません。そのため慣習的に tv.Value != nil と書かれています。これには次の問題があります。
- 意図が分かりにくい。フィールドの nil チェックが「定数判定」を意味するという前提知識が必要になる。
IsValue()と紛らわしい。IsValue()は式が「値」(変数、関数呼び出しの結果、定数などを含む)かどうかを返すもので、定数判定ではない。名前が似ているため取り違えやすい。
提案者によると、x/tools には説明のないtv.Value != nilが多くあり、もともと難しい解析コードをさらに読みにくくしています。
提案された解決策
// IsConstant reports whether tv represents a constant.
func (tv TypeAndValue) IsConstant() bool { return tv.Value != nil }
動作は既存のイディオムとまったく同じです。追加されるのはメソッド1つで、新しい意味論は導入されません。
これによって何ができるようになるか
主な利用者は、静的解析ツール、linter、コード生成ツール、gopls などを書く上級者です。
- 定数畳み込みや定数式の検出:
lenの引数や配列サイズが定数かどうかの判定などを、読みやすく書けます。 - 解析器(
go/analysisのアナライザ)の診断ロジック:例えば「定数のシフト量が範囲外」「定数の比較が常に真になる」といった検査で、条件の意図が明確になります。 - コードレビューと保守:
IsValue()との取り違えによるバグが起きにくくなり、x/tools などの大規模コードベースが読みやすくなります。
コード例
// Before: 意図が分かりにくく、IsValue と混同しやすい
tv := info.Types[expr]
if tv.Value != nil { // 定数かどうか?
fmt.Println("constant:", tv.Value)
}
if tv.IsValue() { // 定数判定ではない(変数や呼び出し結果も true)
// ...
}
// After: 意図が名前から読み取れる
tv := info.Types[expr]
if tv.IsConstant() {
fmt.Println("constant:", tv.Value)
}
議論のハイライト
- 提案の主眼は機能の追加ではなく可読性です。
tv.IsConstant()はtv.Value != nilより明確だという主張です。 - 既存の
IsValue()は「値を表す式か」を判定するもので、定数以外の値でも true を返します。この名前の近さによる混乱を避けることも動機になっています。 - 動機の根拠は、x/tools で
tv.Value != nilが説明なしに多用されているという実例です。 - 現時点では反対意見や代替案(名前の変更など)は出ていません。今後の審議では、既存の述語メソッド群との命名の一貫性や、型チェッカーの内部表現(
mode == constant_)と完全に一致するかが確認されると考えられます。 - 純粋な追加なので後方互換性への影響はなく、パフォーマンスへの影響もありません。