aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/syntax
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2020-12-15 21:07:47 -0800
committerRobert Griesemer <gri@golang.org>2020-12-16 18:41:36 +0000
commit7909d6ec284da0e6a45bdf8fc2afdbb8bbcaeec2 (patch)
tree90b3a566f69f587ee38448e04a83e7f9b2649d58 /src/cmd/compile/internal/syntax
parent3b5918c757eb32b4a05a0b4ba4bbab001175ebf0 (diff)
downloadgo-7909d6ec284da0e6a45bdf8fc2afdbb8bbcaeec2.tar.gz
go-7909d6ec284da0e6a45bdf8fc2afdbb8bbcaeec2.zip
[dev.typeparams] cmd/compile/internal/syntax: type parameters must always be named
Report an error otherwise. Change-Id: Ia76ea03a3f26b13dd9bca49f7bd42101d1ff1f9e Reviewed-on: https://go-review.googlesource.com/c/go/+/278475 Trust: Robert Griesemer <gri@golang.org> Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/cmd/compile/internal/syntax')
-rw-r--r--src/cmd/compile/internal/syntax/error_test.go6
-rw-r--r--src/cmd/compile/internal/syntax/parser.go34
-rw-r--r--src/cmd/compile/internal/syntax/testdata/tparams.go222
3 files changed, 51 insertions, 11 deletions
diff --git a/src/cmd/compile/internal/syntax/error_test.go b/src/cmd/compile/internal/syntax/error_test.go
index 72b1ad6333..919667f1d3 100644
--- a/src/cmd/compile/internal/syntax/error_test.go
+++ b/src/cmd/compile/internal/syntax/error_test.go
@@ -128,6 +128,10 @@ func testSyntaxErrors(t *testing.T, filename string) {
}
defer f.Close()
+ var mode Mode
+ if strings.HasSuffix(filename, ".go2") {
+ mode = AllowGenerics
+ }
ParseFile(filename, func(err error) {
e, ok := err.(Error)
if !ok {
@@ -162,7 +166,7 @@ func testSyntaxErrors(t *testing.T, filename string) {
} else {
t.Errorf("%s: unexpected error: %s", orig, e.Msg)
}
- }, nil, 0)
+ }, nil, mode)
if *print {
fmt.Println()
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go
index 90b67def0f..e3fb1003a2 100644
--- a/src/cmd/compile/internal/syntax/parser.go
+++ b/src/cmd/compile/internal/syntax/parser.go
@@ -595,7 +595,7 @@ func (p *parser) typeDecl(group *Group) Decl {
p.xnest--
if name0, ok := x.(*Name); p.mode&AllowGenerics != 0 && ok && p.tok != _Rbrack {
// generic type
- d.TParamList = p.paramList(name0, _Rbrack)
+ d.TParamList = p.paramList(name0, _Rbrack, true)
pos := p.pos()
if p.gotAssign() {
p.syntaxErrorAt(pos, "generic type cannot be alias")
@@ -664,7 +664,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
f.Pragma = p.takePragma()
if p.got(_Lparen) {
- rcvr := p.paramList(nil, _Rparen)
+ rcvr := p.paramList(nil, _Rparen, false)
switch len(rcvr) {
case 0:
p.error("method has no receiver")
@@ -688,7 +688,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
p.syntaxError("empty type parameter list")
p.next()
} else {
- f.TParamList = p.paramList(nil, _Rbrack)
+ f.TParamList = p.paramList(nil, _Rbrack, true)
}
}
f.Type = p.funcType()
@@ -1313,7 +1313,7 @@ func (p *parser) funcType() *FuncType {
typ := new(FuncType)
typ.pos = p.pos()
p.want(_Lparen)
- typ.ParamList = p.paramList(nil, _Rparen)
+ typ.ParamList = p.paramList(nil, _Rparen, false)
typ.ResultList = p.funcResult()
return typ
@@ -1453,7 +1453,7 @@ func (p *parser) funcResult() []*Field {
}
if p.got(_Lparen) {
- return p.paramList(nil, _Rparen)
+ return p.paramList(nil, _Rparen, false)
}
pos := p.pos()
@@ -1677,7 +1677,7 @@ func (p *parser) methodDecl() *Field {
// A type argument list looks like a parameter list with only
// types. Parse a parameter list and decide afterwards.
- list := p.paramList(nil, _Rbrack)
+ list := p.paramList(nil, _Rbrack, false)
if len(list) == 0 {
// The type parameter list is not [] but we got nothing
// due to other errors (reported by paramList). Treat
@@ -1792,7 +1792,8 @@ func (p *parser) paramDeclOrNil(name *Name) *Field {
// ParameterList = ParameterDecl { "," ParameterDecl } .
// "(" or "[" has already been consumed.
// If name != nil, it is the first name after "(" or "[".
-func (p *parser) paramList(name *Name, close token) (list []*Field) {
+// In the result list, either all fields have a name, or no field has a name.
+func (p *parser) paramList(name *Name, close token, requireNames bool) (list []*Field) {
if trace {
defer p.trace("paramList")()
}
@@ -1813,7 +1814,11 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) {
return false
})
- // distribute parameter types
+ if len(list) == 0 {
+ return
+ }
+
+ // distribute parameter types (len(list) > 0)
if named == 0 {
// all unnamed => found names are named types
for _, par := range list {
@@ -1822,9 +1827,12 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) {
par.Name = nil
}
}
+ if requireNames {
+ p.syntaxErrorAt(list[0].Type.Pos(), "type parameters must be named")
+ }
} else if named != len(list) {
// some named => all must have names and types
- var pos Pos // error position (or unknown)
+ var pos Pos // left-most error position (or unknown)
var typ Expr
for i := len(list) - 1; i >= 0; i-- {
if par := list[i]; par.Type != nil {
@@ -1844,7 +1852,13 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) {
}
}
if pos.IsKnown() {
- p.syntaxErrorAt(pos, "mixed named and unnamed parameters")
+ var msg string
+ if requireNames {
+ msg = "type parameters must be named"
+ } else {
+ msg = "mixed named and unnamed parameters"
+ }
+ p.syntaxErrorAt(pos, msg)
}
}
diff --git a/src/cmd/compile/internal/syntax/testdata/tparams.go2 b/src/cmd/compile/internal/syntax/testdata/tparams.go2
new file mode 100644
index 0000000000..42031c3277
--- /dev/null
+++ b/src/cmd/compile/internal/syntax/testdata/tparams.go2
@@ -0,0 +1,22 @@
+// Copyright 2020 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 t[ /* ERROR type parameters must be named */ a, b] struct{}
+type t[a t, b t, /* ERROR type parameters must be named */ c] struct{}
+type t struct {
+ t [n]byte
+ t[a]
+ t[a, b]
+}
+type t interface {
+ t[a]
+ m /* ERROR method cannot have type parameters */ [_ _, /* ERROR mixed */ _]()
+ t[a, b]
+}
+
+func f[ /* ERROR empty type parameter list */ ]()
+func f[ /* ERROR type parameters must be named */ a, b]()
+func f[a t, b t, /* ERROR type parameters must be named */ c]()