diff options
| author | Robert Griesemer <gri@google.com> | 2026-02-18 14:41:50 -0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-09 12:16:20 -0700 |
| commit | e84da0405bcf64c7dbaafb0afc14388049a9b6fc (patch) | |
| tree | cee6be97994cdf4ee43f8eb13302e6c9aeda451a /src/cmd | |
| parent | d4ace6b007224ef71348f500f1515510bd2c282c (diff) | |
| download | go-e84da0405bcf64c7dbaafb0afc14388049a9b6fc.tar.xz | |
cmd/compile, go/*: allow generic methods starting with Go 1.27
This only changes the type checkers and tests.
Backend compiler changes are not included.
For #77273.
Change-Id: I8cf0b6fddf6afd6b08b06ba6fdf9c726af4bea8d
Reviewed-on: https://go-review.googlesource.com/c/go/+/746820
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/types2/resolver.go | 22 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/version.go | 1 |
2 files changed, 12 insertions, 11 deletions
diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index 0911ae9c90..ef9d0ed4ec 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -415,22 +415,27 @@ func (check *Checker) collectObjects() { case *syntax.FuncDecl: name := s.Name.Value - obj := NewFunc(s.Name.Pos(), pkg, name, nil) - hasTParamError := false // avoid duplicate type parameter errors + obj := NewFunc(s.Name.Pos(), pkg, name, nil) // signature set later + var tparam0 *syntax.Field + if len(s.TParamList) > 0 { + tparam0 = s.TParamList[0] + } if s.Recv == nil { // regular function if name == "init" || name == "main" && pkg.name == "main" { + // init and main functions must not declare type and ordinary parameters or results code := InvalidInitDecl if name == "main" { code = InvalidMainDecl } - if len(s.TParamList) != 0 { - check.softErrorf(s.TParamList[0], code, "func %s must have no type parameters", name) - hasTParamError = true + if tparam0 != nil { + check.softErrorf(tparam0, code, "func %s must have no type parameters", name) } if t := s.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 { check.softErrorf(s.Name, code, "func %s must have no arguments and no return values", name) } + } else { + _ = tparam0 != nil && check.verifyVersionf(tparam0, go1_18, "type parameter") } // don't declare init functions in the package scope - they are invisible if name == "init" { @@ -452,14 +457,9 @@ func (check *Checker) collectObjects() { if recv, _ := base.(*syntax.Name); recv != nil && name != "_" { methods = append(methods, methodInfo{obj, ptr, recv}) } - // methods cannot have type parameters for now - if len(s.TParamList) != 0 { - check.softErrorf(s.TParamList[0], InvalidMethodTypeParams, "method %s must have no type parameters", name) - hasTParamError = true - } + _ = tparam0 != nil && check.verifyVersionf(tparam0, go1_27, "generic method") check.recordDef(s.Name, obj) } - _ = len(s.TParamList) != 0 && !hasTParamError && check.verifyVersionf(s.TParamList[0], go1_18, "type parameter") info := &declInfo{file: fileScope, version: check.version, fdecl: s} // Methods are not package-level objects but we still track them in the // object map so that we can handle them like regular functions (if the diff --git a/src/cmd/compile/internal/types2/version.go b/src/cmd/compile/internal/types2/version.go index 512285055c..05cb9391b9 100644 --- a/src/cmd/compile/internal/types2/version.go +++ b/src/cmd/compile/internal/types2/version.go @@ -44,6 +44,7 @@ var ( go1_22 = asGoVersion("go1.22") go1_23 = asGoVersion("go1.23") go1_26 = asGoVersion("go1.26") + go1_27 = asGoVersion("go1.27") // current (deployed) Go version go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version)) |
