cmd/compile/internal/syntax: better error message when type parameters are not permitted

Fixes #48382.

Change-Id: I215896a4429839c41c9136b6922b1b748ed47734
Reviewed-on: https://go-review.googlesource.com/c/go/+/361259
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-11-03 14:58:59 -07:00
parent 9cf6711067
commit a419f2f5c3
2 changed files with 43 additions and 17 deletions

View file

@ -708,15 +708,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
} }
f.Name = p.name() f.Name = p.name()
if p.allowGenerics() && p.got(_Lbrack) { f.TParamList, f.Type = p.funcType("")
if p.tok == _Rbrack {
p.syntaxError("empty type parameter list")
p.next()
} else {
f.TParamList = p.paramList(nil, _Rbrack, true)
}
}
f.Type = p.funcType()
if p.tok == _Lbrace { if p.tok == _Lbrace {
f.Body = p.funcBody() f.Body = p.funcBody()
} }
@ -944,7 +936,7 @@ func (p *parser) operand(keep_parens bool) Expr {
case _Func: case _Func:
pos := p.pos() pos := p.pos()
p.next() p.next()
ftyp := p.funcType() _, ftyp := p.funcType("function literal")
if p.tok == _Lbrace { if p.tok == _Lbrace {
p.xnest++ p.xnest++
@ -1284,7 +1276,8 @@ func (p *parser) typeOrNil() Expr {
case _Func: case _Func:
// fntype // fntype
p.next() p.next()
return p.funcType() _, t := p.funcType("function type")
return t
case _Lbrack: case _Lbrack:
// '[' oexpr ']' ntype // '[' oexpr ']' ntype
@ -1357,18 +1350,34 @@ func (p *parser) typeInstance(typ Expr) Expr {
return x return x
} }
func (p *parser) funcType() *FuncType { // If context != "", type parameters are not permitted.
func (p *parser) funcType(context string) ([]*Field, *FuncType) {
if trace { if trace {
defer p.trace("funcType")() defer p.trace("funcType")()
} }
typ := new(FuncType) typ := new(FuncType)
typ.pos = p.pos() typ.pos = p.pos()
var tparamList []*Field
if p.allowGenerics() && p.got(_Lbrack) {
if context != "" {
// accept but complain
p.syntaxErrorAt(typ.pos, context+" cannot have type parameters")
}
if p.tok == _Rbrack {
p.syntaxError("empty type parameter list")
p.next()
} else {
tparamList = p.paramList(nil, _Rbrack, true)
}
}
p.want(_Lparen) p.want(_Lparen)
typ.ParamList = p.paramList(nil, _Rparen, false) typ.ParamList = p.paramList(nil, _Rparen, false)
typ.ResultList = p.funcResult() typ.ResultList = p.funcResult()
return typ return tparamList, typ
} }
// "[" has already been consumed, and pos is its position. // "[" has already been consumed, and pos is its position.
@ -1697,11 +1706,13 @@ func (p *parser) methodDecl() *Field {
// already progressed, no need to advance // already progressed, no need to advance
} }
const context = "interface method"
switch p.tok { switch p.tok {
case _Lparen: case _Lparen:
// method // method
f.Name = name f.Name = name
f.Type = p.funcType() _, f.Type = p.funcType(context)
case _Lbrack: case _Lbrack:
if p.allowGenerics() { if p.allowGenerics() {
@ -1721,7 +1732,7 @@ func (p *parser) methodDecl() *Field {
// name[]( // name[](
p.errorAt(pos, "empty type parameter list") p.errorAt(pos, "empty type parameter list")
f.Name = name f.Name = name
f.Type = p.funcType() _, f.Type = p.funcType(context)
} else { } else {
p.errorAt(pos, "empty type argument list") p.errorAt(pos, "empty type argument list")
f.Type = name f.Type = name
@ -1738,7 +1749,7 @@ func (p *parser) methodDecl() *Field {
// as if [] were absent. // as if [] were absent.
if p.tok == _Lparen { if p.tok == _Lparen {
f.Name = name f.Name = name
f.Type = p.funcType() _, f.Type = p.funcType(context)
} else { } else {
f.Type = name f.Type = name
} }
@ -1749,7 +1760,7 @@ func (p *parser) methodDecl() *Field {
if list[0].Name != nil { if list[0].Name != nil {
// generic method // generic method
f.Name = name f.Name = name
f.Type = p.funcType() _, f.Type = p.funcType(context)
// TODO(gri) Record list as type parameter list with f.Type // TODO(gri) Record list as type parameter list with f.Type
// if we want to type-check the generic method. // if we want to type-check the generic method.
// For now, report an error so this is not a silent event. // For now, report an error so this is not a silent event.

View file

@ -0,0 +1,15 @@
// 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 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]()
var _ = func /* ERROR function literal cannot have type parameters */ [P any]() {}
type _ interface{
m /* ERROR interface method cannot have type parameters */ [P any]()
}