メインコンテンツへスキップ
#81822active

spec: ignore channel direction during loose unification

ステータス変更: likely_accept active

要約

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

概要

型パラメータの制約に「方向付きチャネル型」(chan<- E や <-chan E)が混ざっていると、要素型 E が推論できなくなる問題を解消する言語仕様の変更提案です。型推論の「loose unification(緩い単一化)」の段階でチャネルの方向を無視するようにします。

ステータス変更

likely_accept → active
2026年11月4日のレビューで、仕様の差分付きで一度 likely accept とされました。翌日、@Merovius が「提案本文の例 Close は成立しない」と指摘しました。close は送信可能なチャネルにしか使えないため、<-chan E を含む制約では関数本体の型チェックで弾かれます。参考になった #69153 の例も close ではなく cap を使っています。@Merovius 自身は「推論の話なので提案の本質には影響しない」と添えています。これを受けて @aclements が「likely accept から外し、@griesemer が考え直す」と述べ、active に戻りました。issue 上には、指摘以外の差し戻し理由は書かれていません。仕様の文言や設計を詰め直すための差し戻しと考えられます。

技術的背景

現状の問題点

Goの型推論では、引数の型と制約を突き合わせて型引数を決めます。現在の仕様では、制約の型集合がすべて同じ要素型のチャネルであり、かつ方向が衝突しないこと(core type、つまり型集合に共通する基底型が存在すること)が推論の条件です。chan T | <-chan T なら推論できますが、chan T | <-chan T | chan<- T のように送信専用と受信専用が両方入ると推論できません。これは廃止が進む core type 概念の名残です。

type channelConstraint[T any] interface {
	chan T | <-chan T | chan<- T
}
func printCap[T any, C channelConstraint[T]](ch C) { fmt.Println(cap(ch)) }
var r <-chan int = make(chan int, 1)
printCap(r) // error: cannot infer T

提案された解決策

仕様の型単一化ルールを次のように変更します。

  • 制約 C の型集合がすべて同じ要素型のチャネル型である場合、条件から「方向が衝突しないこと」を削除します。そのうえで「最も制限的なチャネル型」ではなく「任意のチャネル型」と型引数 A を緩く単一化します。
  • loose unification のルールに次の項目を追加します。「両方がチャネル型で、要素型が単一化できればよい。チャネルの方向は無視する。」
    既存のプログラムの動作は変わらず、受理されるプログラムが増えるだけなので、後方互換性があります。コストは、コンパイラの単一化処理への関数1つの追加と、制約ごとに1回の型アサーションです。

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

方向を問わずチャネルを受け取る汎用ヘルパーを、型引数を明示せずに呼べるようになります。

  • len/cap を使ってバッファの使用状況を監視するユーティリティ
  • 送受信の方向が混在するコードベースでの共通ヘルパー(ログ出力、メトリクス収集など)
  • チャネルを抽象化するジェネリックなライブラリAPI

コード例

// Before: 要素型を明示する必要がある
printCap[string](sendOnlyCh)
printCap[int](receiveOnlyCh)
printCap[any](bidiCh)
// After: 方向に関係なく要素型が推論される
printCap(sendOnlyCh)
printCap(receiveOnlyCh)
printCap(bidiCh)

議論のハイライト

  • 提案者の @mcy は、プロトタイプ実装 CL 829606 を用意したうえで提案しています。この CL は既知のバグ #69153 の修正にもなります。
  • #69153 で @griesemer は、原因を「制約に core type がないこと」と説明しています。chan T | <-chan T なら推論できますが、その場合は制約に含まれない方向のチャネルで関数を実体化(インスタンス化)できない、というジレンマも指摘しています。
  • @Merovius は、提案本文の close の例はそもそも型チェックを通らないと指摘しました。推論の話なので本質的な影響はないとしています。この指摘が likely accept からの差し戻しのきっかけになりました。
  • 関連する議論として、チャネル型の推論の柔軟化(#45920、#65202)、十分に制約された制約からの推論(#73527)、len/cap などの組み込み関数に対する core type 制限の撤廃(#63940)があります。

関連リンク