Skip to content

Commit a419f2f

Browse files
committed
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 <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 9cf6711 commit a419f2f

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

src/cmd/compile/internal/syntax/parser.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -708,15 +708,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
708708
}
709709

710710
f.Name = p.name()
711-
if p.allowGenerics() && p.got(_Lbrack) {
712-
if p.tok == _Rbrack {
713-
p.syntaxError("empty type parameter list")
714-
p.next()
715-
} else {
716-
f.TParamList = p.paramList(nil, _Rbrack, true)
717-
}
718-
}
719-
f.Type = p.funcType()
711+
f.TParamList, f.Type = p.funcType("")
720712
if p.tok == _Lbrace {
721713
f.Body = p.funcBody()
722714
}
@@ -944,7 +936,7 @@ func (p *parser) operand(keep_parens bool) Expr {
944936
case _Func:
945937
pos := p.pos()
946938
p.next()
947-
ftyp := p.funcType()
939+
_, ftyp := p.funcType("function literal")
948940
if p.tok == _Lbrace {
949941
p.xnest++
950942

@@ -1284,7 +1276,8 @@ func (p *parser) typeOrNil() Expr {
12841276
case _Func:
12851277
// fntype
12861278
p.next()
1287-
return p.funcType()
1279+
_, t := p.funcType("function type")
1280+
return t
12881281

12891282
case _Lbrack:
12901283
// '[' oexpr ']' ntype
@@ -1357,18 +1350,34 @@ func (p *parser) typeInstance(typ Expr) Expr {
13571350
return x
13581351
}
13591352

1360-
func (p *parser) funcType() *FuncType {
1353+
// If context != "", type parameters are not permitted.
1354+
func (p *parser) funcType(context string) ([]*Field, *FuncType) {
13611355
if trace {
13621356
defer p.trace("funcType")()
13631357
}
13641358

13651359
typ := new(FuncType)
13661360
typ.pos = p.pos()
1361+
1362+
var tparamList []*Field
1363+
if p.allowGenerics() && p.got(_Lbrack) {
1364+
if context != "" {
1365+
// accept but complain
1366+
p.syntaxErrorAt(typ.pos, context+" cannot have type parameters")
1367+
}
1368+
if p.tok == _Rbrack {
1369+
p.syntaxError("empty type parameter list")
1370+
p.next()
1371+
} else {
1372+
tparamList = p.paramList(nil, _Rbrack, true)
1373+
}
1374+
}
1375+
13671376
p.want(_Lparen)
13681377
typ.ParamList = p.paramList(nil, _Rparen, false)
13691378
typ.ResultList = p.funcResult()
13701379

1371-
return typ
1380+
return tparamList, typ
13721381
}
13731382

13741383
// "[" has already been consumed, and pos is its position.
@@ -1697,11 +1706,13 @@ func (p *parser) methodDecl() *Field {
16971706
// already progressed, no need to advance
16981707
}
16991708

1709+
const context = "interface method"
1710+
17001711
switch p.tok {
17011712
case _Lparen:
17021713
// method
17031714
f.Name = name
1704-
f.Type = p.funcType()
1715+
_, f.Type = p.funcType(context)
17051716

17061717
case _Lbrack:
17071718
if p.allowGenerics() {
@@ -1721,7 +1732,7 @@ func (p *parser) methodDecl() *Field {
17211732
// name[](
17221733
p.errorAt(pos, "empty type parameter list")
17231734
f.Name = name
1724-
f.Type = p.funcType()
1735+
_, f.Type = p.funcType(context)
17251736
} else {
17261737
p.errorAt(pos, "empty type argument list")
17271738
f.Type = name
@@ -1738,7 +1749,7 @@ func (p *parser) methodDecl() *Field {
17381749
// as if [] were absent.
17391750
if p.tok == _Lparen {
17401751
f.Name = name
1741-
f.Type = p.funcType()
1752+
_, f.Type = p.funcType(context)
17421753
} else {
17431754
f.Type = name
17441755
}
@@ -1749,7 +1760,7 @@ func (p *parser) methodDecl() *Field {
17491760
if list[0].Name != nil {
17501761
// generic method
17511762
f.Name = name
1752-
f.Type = p.funcType()
1763+
_, f.Type = p.funcType(context)
17531764
// TODO(gri) Record list as type parameter list with f.Type
17541765
// if we want to type-check the generic method.
17551766
// For now, report an error so this is not a silent event.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type _ func /* ERROR function type cannot have type parameters */ [ /* ERROR empty type parameter list */ ]()
8+
type _ func /* ERROR function type cannot have type parameters */ [ x /* ERROR missing type constraint */ ]()
9+
type _ func /* ERROR function type cannot have type parameters */ [P any]()
10+
11+
var _ = func /* ERROR function literal cannot have type parameters */ [P any]() {}
12+
13+
type _ interface{
14+
m /* ERROR interface method cannot have type parameters */ [P any]()
15+
}

0 commit comments

Comments
 (0)