mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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>
This commit is contained in:
parent
3b5918c757
commit
7909d6ec28
3 changed files with 51 additions and 11 deletions
|
|
@ -128,6 +128,10 @@ func testSyntaxErrors(t *testing.T, filename string) {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
var mode Mode
|
||||||
|
if strings.HasSuffix(filename, ".go2") {
|
||||||
|
mode = AllowGenerics
|
||||||
|
}
|
||||||
ParseFile(filename, func(err error) {
|
ParseFile(filename, func(err error) {
|
||||||
e, ok := err.(Error)
|
e, ok := err.(Error)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -162,7 +166,7 @@ func testSyntaxErrors(t *testing.T, filename string) {
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("%s: unexpected error: %s", orig, e.Msg)
|
t.Errorf("%s: unexpected error: %s", orig, e.Msg)
|
||||||
}
|
}
|
||||||
}, nil, 0)
|
}, nil, mode)
|
||||||
|
|
||||||
if *print {
|
if *print {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,7 @@ func (p *parser) typeDecl(group *Group) Decl {
|
||||||
p.xnest--
|
p.xnest--
|
||||||
if name0, ok := x.(*Name); p.mode&AllowGenerics != 0 && ok && p.tok != _Rbrack {
|
if name0, ok := x.(*Name); p.mode&AllowGenerics != 0 && ok && p.tok != _Rbrack {
|
||||||
// generic type
|
// generic type
|
||||||
d.TParamList = p.paramList(name0, _Rbrack)
|
d.TParamList = p.paramList(name0, _Rbrack, true)
|
||||||
pos := p.pos()
|
pos := p.pos()
|
||||||
if p.gotAssign() {
|
if p.gotAssign() {
|
||||||
p.syntaxErrorAt(pos, "generic type cannot be alias")
|
p.syntaxErrorAt(pos, "generic type cannot be alias")
|
||||||
|
|
@ -664,7 +664,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
|
||||||
f.Pragma = p.takePragma()
|
f.Pragma = p.takePragma()
|
||||||
|
|
||||||
if p.got(_Lparen) {
|
if p.got(_Lparen) {
|
||||||
rcvr := p.paramList(nil, _Rparen)
|
rcvr := p.paramList(nil, _Rparen, false)
|
||||||
switch len(rcvr) {
|
switch len(rcvr) {
|
||||||
case 0:
|
case 0:
|
||||||
p.error("method has no receiver")
|
p.error("method has no receiver")
|
||||||
|
|
@ -688,7 +688,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
|
||||||
p.syntaxError("empty type parameter list")
|
p.syntaxError("empty type parameter list")
|
||||||
p.next()
|
p.next()
|
||||||
} else {
|
} else {
|
||||||
f.TParamList = p.paramList(nil, _Rbrack)
|
f.TParamList = p.paramList(nil, _Rbrack, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.Type = p.funcType()
|
f.Type = p.funcType()
|
||||||
|
|
@ -1313,7 +1313,7 @@ func (p *parser) funcType() *FuncType {
|
||||||
typ := new(FuncType)
|
typ := new(FuncType)
|
||||||
typ.pos = p.pos()
|
typ.pos = p.pos()
|
||||||
p.want(_Lparen)
|
p.want(_Lparen)
|
||||||
typ.ParamList = p.paramList(nil, _Rparen)
|
typ.ParamList = p.paramList(nil, _Rparen, false)
|
||||||
typ.ResultList = p.funcResult()
|
typ.ResultList = p.funcResult()
|
||||||
|
|
||||||
return typ
|
return typ
|
||||||
|
|
@ -1453,7 +1453,7 @@ func (p *parser) funcResult() []*Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.got(_Lparen) {
|
if p.got(_Lparen) {
|
||||||
return p.paramList(nil, _Rparen)
|
return p.paramList(nil, _Rparen, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pos := p.pos()
|
pos := p.pos()
|
||||||
|
|
@ -1677,7 +1677,7 @@ func (p *parser) methodDecl() *Field {
|
||||||
|
|
||||||
// A type argument list looks like a parameter list with only
|
// A type argument list looks like a parameter list with only
|
||||||
// types. Parse a parameter list and decide afterwards.
|
// types. Parse a parameter list and decide afterwards.
|
||||||
list := p.paramList(nil, _Rbrack)
|
list := p.paramList(nil, _Rbrack, false)
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
// The type parameter list is not [] but we got nothing
|
// The type parameter list is not [] but we got nothing
|
||||||
// due to other errors (reported by paramList). Treat
|
// due to other errors (reported by paramList). Treat
|
||||||
|
|
@ -1792,7 +1792,8 @@ func (p *parser) paramDeclOrNil(name *Name) *Field {
|
||||||
// ParameterList = ParameterDecl { "," ParameterDecl } .
|
// ParameterList = ParameterDecl { "," ParameterDecl } .
|
||||||
// "(" or "[" has already been consumed.
|
// "(" or "[" has already been consumed.
|
||||||
// If name != nil, it is the first name after "(" or "[".
|
// 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 {
|
if trace {
|
||||||
defer p.trace("paramList")()
|
defer p.trace("paramList")()
|
||||||
}
|
}
|
||||||
|
|
@ -1813,7 +1814,11 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) {
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
// distribute parameter types
|
if len(list) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// distribute parameter types (len(list) > 0)
|
||||||
if named == 0 {
|
if named == 0 {
|
||||||
// all unnamed => found names are named types
|
// all unnamed => found names are named types
|
||||||
for _, par := range list {
|
for _, par := range list {
|
||||||
|
|
@ -1822,9 +1827,12 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) {
|
||||||
par.Name = nil
|
par.Name = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if requireNames {
|
||||||
|
p.syntaxErrorAt(list[0].Type.Pos(), "type parameters must be named")
|
||||||
|
}
|
||||||
} else if named != len(list) {
|
} else if named != len(list) {
|
||||||
// some named => all must have names and types
|
// 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
|
var typ Expr
|
||||||
for i := len(list) - 1; i >= 0; i-- {
|
for i := len(list) - 1; i >= 0; i-- {
|
||||||
if par := list[i]; par.Type != nil {
|
if par := list[i]; par.Type != nil {
|
||||||
|
|
@ -1844,7 +1852,13 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pos.IsKnown() {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
22
src/cmd/compile/internal/syntax/testdata/tparams.go2
vendored
Normal file
22
src/cmd/compile/internal/syntax/testdata/tparams.go2
vendored
Normal file
|
|
@ -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]()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue