}
f.Name = p.name()
- f.TParamList, f.Type = p.funcType("")
+
+ context := ""
+ if f.Recv != nil && p.mode&AllowMethodTypeParams == 0 {
+ context = "method" // don't permit (method) type parameters in funcType
+ }
+ f.TParamList, f.Type = p.funcType(context)
+
if p.tok == _Lbrace {
f.Body = p.funcBody()
}
if p.allowGenerics() && p.got(_Lbrack) {
if context != "" {
// accept but complain
- p.syntaxErrorAt(typ.pos, context+" cannot have type parameters")
+ p.syntaxErrorAt(typ.pos, context+" must have no type parameters")
}
if p.tok == _Rbrack {
p.syntaxError("empty type parameter list")
// TODO(gri) Record list as type parameter list with f.Type
// if we want to type-check the generic method.
// For now, report an error so this is not a silent event.
- p.errorAt(pos, "interface method cannot have type parameters")
+ p.errorAt(pos, "interface method must have no type parameters")
break
}
for _, fi := range list {
name := fi.Name()
if !fi.IsDir() && !strings.HasPrefix(name, ".") {
- ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics)
+ ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowMethodTypeParams)
}
}
}
const (
CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements
AllowGenerics
+ AllowMethodTypeParams // does not support interface methods yet; ignored if AllowGenerics is not set
)
// Error describes a syntax error. Error implements the error interface.
package p
-type _ func /* ERROR function type cannot have type parameters */ [ /* ERROR empty type parameter list */ ]()
-type _ func /* ERROR function type cannot have type parameters */ [ x /* ERROR missing type constraint */ ]()
-type _ func /* ERROR function type cannot have type parameters */ [P any]()
+type _ func /* ERROR function type must have no type parameters */ [ /* ERROR empty type parameter list */ ]()
+type _ func /* ERROR function type must have no type parameters */ [ x /* ERROR missing type constraint */ ]()
+type _ func /* ERROR function type must have no type parameters */ [P any]()
-var _ = func /* ERROR function literal cannot have type parameters */ [P any]() {}
+var _ = func /* ERROR function literal must have no type parameters */ [P any]() {}
type _ interface{
- m /* ERROR interface method cannot have type parameters */ [P any]()
+ m /* ERROR interface method must have no type parameters */ [P any]()
}
}
type t interface {
t[a]
- m /* ERROR method cannot have type parameters */ [_ _, /* ERROR mixed */ _]()
+ m /* ERROR method must have no type parameters */ [_ _, /* ERROR mixed */ _]()
t[a, b]
}
func parseSrc(path, src string) (*syntax.File, error) {
errh := func(error) {} // dummy error handler so that parsing continues in presence of errors
- return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics)
+ return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics|syntax.AllowMethodTypeParams)
}
func pkgFor(path, source string, info *Info) (*Package, error) {
var mode syntax.Mode
if strings.HasSuffix(filenames[0], ".go2") || manual {
- mode |= syntax.AllowGenerics
+ mode |= syntax.AllowGenerics | syntax.AllowMethodTypeParams
}
// parse files and collect parser errors
files, errlist := parseFiles(t, filenames, mode)
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 && !acceptMethodTypeParams {
- check.error(f.Type, "methods cannot have type parameters")
- }
-
// use named receiver type if available (for better error messages)
var recvTyp Type = ityp
if def != nil {
return m, typ != nil
}
+// If we accept type parameters for methods, (at least) the code
+// guarded with this constant will need to be adjusted when such
+// methods are used (not just parsed).
+const acceptMethodTypeParams = false
+
// missingMethod is like MissingMethod but accepts a *Checker as
// receiver and an addressable flag.
// The receiver may be nil if missingMethod is invoked through
} else {
// method
// d.Recv != nil
- if !acceptMethodTypeParams && len(s.TParamList) != 0 {
- //check.error(d.TParamList.Pos(), invalidAST + "method must have no type parameters")
- check.error(s.TParamList[0], invalidAST+"method must have no type parameters")
- hasTParamError = true
- }
ptr, recv, _ := check.unpackRecv(s.Recv.Type, false)
- // (Methods with invalid receiver cannot be associated to a type, and
+ // Methods with invalid receiver cannot be associated to a type, and
// methods with blank _ names are never found; no need to collect any
- // of them. They will still be type-checked with all the other functions.)
+ // of them. They will still be type-checked with all the other functions.
if recv != nil && name != "_" {
methods = append(methods, methodInfo{obj, ptr, recv})
}
// ----------------------------------------------------------------------------
// Implementation
-// Disabled by default, but enabled when running tests (via types_test.go).
-var acceptMethodTypeParams bool
-
// funcType type-checks a function or method type.
func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []*syntax.Field, ftyp *syntax.FuncType) {
check.openScope(ftyp, "function")
}
if tparams != nil {
+ // The parser will complain about invalid type parameters for methods.
check.collectTypeParams(&sig.tparams, 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 && !acceptMethodTypeParams {
- check.error(ftyp, "methods cannot have type parameters")
- }
}
// Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their
var x T25 /* ERROR without instantiation */ .m1
// crash 26
-type T26 = interface{ F26[ /* ERROR cannot have type parameters */ Z any]() }
+type T26 = interface{ F26[ /* ERROR interface method must have no type parameters */ Z any]() }
func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ [] /* ERROR operand */ }
// crash 27
+++ /dev/null
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
--- /dev/null
+// errorcheck
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S struct{}
+
+func (S) _[_ any]() {} // ERROR "method must have no type parameters"
+
+type _ interface {
+ m[_ any]() // ERROR "method must have no type parameters"
+}