// {`package qf14; type T[_ any] int; func ((*(T[_]))) _() {}`, `(T[_])`, `qf14.T[_]`}, // parser doesn't record parens
// {`package qf15; type T[_ any] int; func ((*(T[_]))) _() {}`, `*(T[_])`, `*qf15.T[_]`}, // parser doesn't record parens
// {`package qf16; type T[_ any] int; func ((*(T[_]))) _() {}`, `(*(T[_]))`, `*qf16.T[_]`}, // parser doesn't record parens
+
+ // For historic reasons, type parameters in receiver type expressions
+ // are considered both definitions and uses and thus also show up in
+ // the Info.Types map (see go.dev/issue/68670).
+ {`package t1; type T[_ any] int; func (T[P]) _() {}`, `P`, `P`},
+ {`package t2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `P`},
+ {`package t3; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `Q`},
}
for _, test := range tests {
{`package g0; type x[T any] int`, `x`, `type g0.x[T any] int`},
{`package g1; func f[T any]() {}`, `f`, `func g1.f[T any]()`},
{`package g2; type x[T any] int; func (*x[_]) m() {}`, `m`, `func (*g2.x[_]).m()`},
+
+ // Type parameters in receiver type expressions are definitions.
+ {`package r0; type T[_ any] int; func (T[P]) _() {}`, `P`, `type parameter P any`},
+ {`package r1; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `type parameter P any`},
+ {`package r2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `type parameter Q any`},
}
for _, test := range tests {
`m`,
`func (m10.E[int]).m()`,
},
+
+ // For historic reasons, type parameters in receiver type expressions
+ // are considered both definitions and uses (see go.dev/issue/68670).
+ {`package r0; type T[_ any] int; func (T[P]) _() {}`, `P`, `type parameter P any`},
+ {`package r1; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `type parameter P any`},
+ {`package r2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `type parameter Q any`},
}
for _, test := range tests {
// after typechecking rbase (see go.dev/issue/52038).
recvTParams := make([]*TypeParam, len(rtparams))
for i, rparam := range rtparams {
- recvTParams[i] = check.declareTypeParam(rparam, scopePos)
+ tpar := check.declareTypeParam(rparam, scopePos)
+ recvTParams[i] = tpar
+ // For historic reasons, type parameters in receiver type expressions
+ // are considered both definitions and uses and thus must be recorded
+ // in the Info.Uses and Info.Types maps (see go.dev/issue/68670).
+ check.recordUse(rparam, tpar.obj)
+ check.recordTypeAndValue(rparam, typexpr, tpar, nil)
}
recvTParamsList = bindTParams(recvTParams)
{`package qf14; type T[_ any] int; func ((*(T[_]))) _() {}`, `(T[_])`, `qf14.T[_]`},
{`package qf15; type T[_ any] int; func ((*(T[_]))) _() {}`, `*(T[_])`, `*qf15.T[_]`},
{`package qf16; type T[_ any] int; func ((*(T[_]))) _() {}`, `(*(T[_]))`, `*qf16.T[_]`},
+
+ // For historic reasons, type parameters in receiver type expressions
+ // are considered both definitions and uses and thus also show up in
+ // the Info.Types map (see go.dev/issue/68670).
+ {`package t1; type T[_ any] int; func (T[P]) _() {}`, `P`, `P`},
+ {`package t2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `P`},
+ {`package t3; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `Q`},
}
for _, test := range tests {
{`package g0; type x[T any] int`, `x`, `type g0.x[T any] int`},
{`package g1; func f[T any]() {}`, `f`, `func g1.f[T any]()`},
{`package g2; type x[T any] int; func (*x[_]) m() {}`, `m`, `func (*g2.x[_]).m()`},
+
+ // Type parameters in receiver type expressions are definitions.
+ {`package r0; type T[_ any] int; func (T[P]) _() {}`, `P`, `type parameter P any`},
+ {`package r1; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `type parameter P any`},
+ {`package r2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `type parameter Q any`},
}
for _, test := range tests {
},
{`package m11; type T[A any] interface{ m(); n() }; func _(t1 T[int], t2 T[string]) { t1.m(); t2.n() }`, `m`, `func (m11.T[int]).m()`},
{`package m12; type T[A any] interface{ m(); n() }; func _(t1 T[int], t2 T[string]) { t1.m(); t2.n() }`, `n`, `func (m12.T[string]).n()`},
+
+ // For historic reasons, type parameters in receiver type expressions
+ // are considered both definitions and uses (see go.dev/issue/68670).
+ {`package r0; type T[_ any] int; func (T[P]) _() {}`, `P`, `type parameter P any`},
+ {`package r1; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `type parameter P any`},
+ {`package r2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `type parameter Q any`},
}
for _, test := range tests {
// list (so we can have mutually recursive parameterized interfaces).
scopePos := list.Pos()
for _, f := range list.List {
- tparams = check.declareTypeParams(tparams, f.Names, scopePos)
+ for _, name := range f.Names {
+ tparams = append(tparams, check.declareTypeParam(name, scopePos))
+ }
}
// Set the type parameters before collecting the type constraints because
return check.typ(x)
}
-func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident, scopePos token.Pos) []*TypeParam {
+func (check *Checker) declareTypeParam(name *ast.Ident, scopePos token.Pos) *TypeParam {
// Use Typ[Invalid] for the type constraint to ensure that a type
// is present even if the actual constraint has not been assigned
// yet.
// TODO(gri) Need to systematically review all uses of type parameter
// constraints to make sure we don't rely on them if they
// are not properly set yet.
- for _, name := range names {
- tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
- tpar := check.newTypeParam(tname, Typ[Invalid]) // assigns type to tpar as a side-effect
- check.declare(check.scope, name, tname, scopePos)
- tparams = append(tparams, tpar)
- }
-
- if check.conf._Trace && len(names) > 0 {
- check.trace(names[0].Pos(), "type params = %v", tparams[len(tparams)-len(names):])
- }
-
- return tparams
+ tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
+ tpar := check.newTypeParam(tname, Typ[Invalid]) // assigns type to tname as a side-effect
+ check.declare(check.scope, name, tname, scopePos)
+ return tpar
}
func (check *Checker) collectMethods(obj *TypeName) {
// Checker.collectTypeParams). The scope of the type parameter T in
// "func (r T[T]) f() {}" starts after f, not at r, so we declare it
// after typechecking rbase (see go.dev/issue/52038).
- recvTParams := check.declareTypeParams(nil, rtparams, scopePos)
+ recvTParams := make([]*TypeParam, len(rtparams))
+ for i, rparam := range rtparams {
+ tpar := check.declareTypeParam(rparam, scopePos)
+ recvTParams[i] = tpar
+ // For historic reasons, type parameters in receiver type expressions
+ // are considered both definitions and uses and thus must be recorded
+ // in the Info.Uses and Info.Types maps (see go.dev/issue/68670).
+ check.recordUse(rparam, tpar.obj)
+ check.recordTypeAndValue(rparam, typexpr, tpar, nil)
+ }
recvTParamsList = bindTParams(recvTParams)
// Get the type parameter bounds from the receiver base type