aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/resolver.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-08-24 18:07:42 -0700
committerRobert Griesemer <gri@golang.org>2021-08-25 23:43:53 +0000
commit4068fb6c2162b38db7912903ff12bafe9f5ca9bb (patch)
tree9bd25a1f5bd6d796bb080499c5cb27a49276f616 /src/cmd/compile/internal/types2/resolver.go
parentbf0bc4122fd4b3a75c2f9c107895cd5e2f89b90e (diff)
downloadgo-4068fb6c2162b38db7912903ff12bafe9f5ca9bb.tar.gz
go-4068fb6c2162b38db7912903ff12bafe9f5ca9bb.zip
cmd/compile: always accept 1.18 syntax but complain if not 1.18
This CL configures the parser to always accept 1.18 syntax (type parameters, type instantiations, interface elements), even when -lang is set to an earlier release. Instead, the type checker looks for 1.18 operations and complains if the language version is set to an earlier release. Doing these checks during type checking is necessary because it it is possible to write "generic" code using pre-1.18 syntax; for instance, an imported generic function may be implicitly instantiated (as in imported.Max(2, 3)), or an imported constraint interface may be embedded in an "ordinary" interface. Fixes #47818. Change-Id: I83ec302b3f4ba7196c0a4743c03670cfb901310d Reviewed-on: https://go-review.googlesource.com/c/go/+/344871 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types2/resolver.go')
-rw-r--r--src/cmd/compile/internal/types2/resolver.go40
1 files changed, 24 insertions, 16 deletions
diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go
index 018a20cfb2..34fbc3d41b 100644
--- a/src/cmd/compile/internal/types2/resolver.go
+++ b/src/cmd/compile/internal/types2/resolver.go
@@ -412,52 +412,60 @@ func (check *Checker) collectObjects() {
}
case *syntax.TypeDecl:
+ if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) {
+ check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+ }
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s})
case *syntax.FuncDecl:
- d := s // TODO(gri) get rid of this
- name := d.Name.Value
- obj := NewFunc(d.Name.Pos(), pkg, name, nil)
- if d.Recv == nil {
+ name := s.Name.Value
+ obj := NewFunc(s.Name.Pos(), pkg, name, nil)
+ hasTParamError := false // avoid duplicate type parameter errors
+ if s.Recv == nil {
// regular function
if name == "init" || name == "main" && pkg.name == "main" {
- if d.TParamList != nil {
- check.softErrorf(d, "func %s must have no type parameters", name)
+ if len(s.TParamList) != 0 {
+ check.softErrorf(s.TParamList[0], "func %s must have no type parameters", name)
+ hasTParamError = true
}
- if t := d.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 {
- check.softErrorf(d, "func %s must have no arguments and no return values", name)
+ if t := s.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 {
+ check.softErrorf(s, "func %s must have no arguments and no return values", name)
}
}
// don't declare init functions in the package scope - they are invisible
if name == "init" {
obj.parent = pkg.scope
- check.recordDef(d.Name, obj)
+ check.recordDef(s.Name, obj)
// init functions must have a body
- if d.Body == nil {
+ if s.Body == nil {
// TODO(gri) make this error message consistent with the others above
check.softErrorf(obj.pos, "missing function body")
}
} else {
- check.declare(pkg.scope, d.Name, obj, nopos)
+ check.declare(pkg.scope, s.Name, obj, nopos)
}
} else {
// method
// d.Recv != nil
- if !acceptMethodTypeParams && len(d.TParamList) != 0 {
+ if !acceptMethodTypeParams && len(s.TParamList) != 0 {
//check.error(d.TParamList.Pos(), invalidAST + "method must have no type parameters")
- check.error(d, 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(d.Recv.Type, false)
+ ptr, recv, _ := check.unpackRecv(s.Recv.Type, false)
// (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.)
if recv != nil && name != "_" {
methods = append(methods, methodInfo{obj, ptr, recv})
}
- check.recordDef(d.Name, obj)
+ check.recordDef(s.Name, obj)
+ }
+ if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError {
+ check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
}
- info := &declInfo{file: fileScope, fdecl: d}
+ info := &declInfo{file: fileScope, 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
// receiver is invalid); also we need their fdecl info when associating