タラバガニー設計局stalins.clubNOTE/notes/phantom-type-parameter

ダミー型パラメータによる instantiation cycle 回避

monomorphization checker が引き起こす instantiation cycle エラーには、実際に動く回避策が存在する。csgura が #80172 (2026-07-08) で示したもので、ダミーの型パラメータを1個足してメソッドをジェネリクスメソッド化すると通る。

type Phantom[T any] = *T
func (Slice[A]) Chunked[_ Phantom[A]](n int) Slice[[]A]

型引数は推論されるので、呼び出し側は何も書かなくてよい。素通りするダミーの型パラメータ _ を足すだけで、monomorphization checker の対象から外れる。

csgura はこの回避策と同時に、制限そのものへの反論も述べている。「ジェネリクスメソッドは呼ばれるまで instantiate されないのに、なぜ宣言時にエラーになるのか」というものだ。次のような例で Slice[A].Zip を instantiate するのに Slice[Tuple[A, B]].Zip の instantiate まで要求されるのはおかしい、という主張である。

type Slice[A any] []A
func (r Slice[A]) Zip[B any](other Slice[B]) Slice[Tuple[A, B]] { panic("") }

しかし Go チームはこの回避策を推奨していない。2026-08-12 の mrkfrmn の結論はこうだ。

On further thought and discussion with team members, we are unlikely to change this, at least for now.

理由は主に2つ。ひとつは、ダミー型パラメータを足すくらいなら素直に関数へ昇格させるべきというもの。もうひとつは、制限を緩和すると chunk() は落ちるのに chunk[_ any]() なら通る、という一貫性のない状態になり混乱を招く、というものだ。ジェネリクスメソッドは interface を満たさない (ジェネリクスメソッドはインターフェースを満たさない) ので理屈上は制限を外せる余地があるにもかかわらず、「混乱を避ける」という運用上の判断が優先された形になる。

具体的な症状の経緯 (griesemer の最小再現や f は通り m は落ちる対比) は 関数だと通りメソッドだと通らないシグネチャ に、制限そのものの原理は monomorphization checker にまとめてある。

出典

  • Go Release Party 1.27 の発表資料リポジトリ memo.md §1、issues.md §2
  • #80172

▸ ノート一覧に戻る