diff --git a/src/go/types/api.go b/src/go/types/api.go index d763fd81a2..6ea2828c32 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -107,6 +107,9 @@ type Config struct { // type-checked. IgnoreFuncBodies bool + // If AcceptMethodTypeParams is set, methods may have type parameters. + AcceptMethodTypeParams bool + // If FakeImportC is set, `import "C"` (for packages requiring Cgo) // declares an empty "C" package and errors are omitted for qualified // identifiers referring to package C (which won't find an object). diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index ea6ba3e702..6f78de1cbb 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -49,8 +49,9 @@ func mayTypecheck(t *testing.T, path, source string, info *Info) (string, error) t.Fatalf("%s: unable to parse: %s", path, err) } conf := Config{ - Error: func(err error) {}, - Importer: importer.Default(), + AcceptMethodTypeParams: true, + Error: func(err error) {}, + Importer: importer.Default(), } pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info) return pkg.Name(), err diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index f6f1142d96..7b3b30571c 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -281,6 +281,7 @@ func checkFiles(t *testing.T, testfiles []string) { // typecheck and collect typechecker errors var conf Config + conf.AcceptMethodTypeParams = true // special case for importC.src if len(testfiles) == 1 && testfiles[0] == "testdata/importC.src" { conf.FakeImportC = true diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index df547cb058..7a788f0550 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -311,6 +311,12 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast if ftyp.TParams != nil { sig.tparams = check.collectTypeParams(ftyp.TParams) + // Always type-check method type parameters but complain if they are not enabled. + // (A separate check is needed when type-checking interface method signatures because + // they don't have a receiver specification.) + if recvPar != nil && !check.conf.AcceptMethodTypeParams { + check.errorf(ftyp.TParams.Pos(), "methods cannot have type parameters") + } } // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their @@ -749,6 +755,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d continue // ignore } + // Always type-check method type parameters but complain if they are not enabled. + // (This extra check is needed here because interface method signatures don't have + // a receiver specification.) + if sig.tparams != nil && !check.conf.AcceptMethodTypeParams { + check.errorf(f.Type.(*ast.FuncType).TParams.Pos(), "methods cannot have type parameters") + } + // use named receiver type if available (for better error messages) var recvTyp Type = ityp if def != nil {