mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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:
parent
9cf6711067
commit
a419f2f5c3
2 changed files with 43 additions and 17 deletions
|
|
@ -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.
|
||||||
|
|
|
||||||
15
src/cmd/compile/internal/syntax/testdata/issue48382.go2
vendored
Normal file
15
src/cmd/compile/internal/syntax/testdata/issue48382.go2
vendored
Normal 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]()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue