1
0
mirror of https://github.com/golang/go synced 2024-09-29 13:24:28 -06:00

go/printer: don't print unnecesary commas for func type param lists

Type parameter lists are not ambiguous for function declarations in the
way that they are ambiguous for type declarations. Avoid printing an
extra comma to disambiguate.

Fixes #51548

Change-Id: I8ca2b21e271982013653b9e220f92ee74f577ba2
Reviewed-on: https://go-review.googlesource.com/c/go/+/390914
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Findley 2022-03-08 16:43:47 -05:00
parent 4469557974
commit 0add0647d8
3 changed files with 67 additions and 8 deletions

View File

@ -319,9 +319,17 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
}
}
func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
type paramMode int
const (
funcParam paramMode = iota
funcTParam
typeTParam
)
func (p *printer) parameters(fields *ast.FieldList, mode paramMode) {
openTok, closeTok := token.LPAREN, token.RPAREN
if isTypeParam {
if mode != funcParam {
openTok, closeTok = token.LBRACK, token.RBRACK
}
p.print(fields.Opening, openTok)
@ -373,7 +381,7 @@ func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
p.print(token.COMMA)
p.linebreak(closing, 0, ignore, true)
} else if isTypeParam && fields.NumFields() == 1 {
} else if mode == typeTParam && fields.NumFields() == 1 {
// Otherwise, if we are in a type parameter list that could be confused
// with the constant array length expression [P*C], print a comma so that
// parsing is unambiguous.
@ -411,10 +419,10 @@ func isTypeLit(x ast.Expr) bool {
func (p *printer) signature(sig *ast.FuncType) {
if sig.TypeParams != nil {
p.parameters(sig.TypeParams, true)
p.parameters(sig.TypeParams, funcTParam)
}
if sig.Params != nil {
p.parameters(sig.Params, false)
p.parameters(sig.Params, funcParam)
} else {
p.print(token.LPAREN, token.RPAREN)
}
@ -428,7 +436,7 @@ func (p *printer) signature(sig *ast.FuncType) {
p.expr(stripParensAlways(res.List[0].Type))
return
}
p.parameters(res, false)
p.parameters(res, funcParam)
}
}
@ -1639,7 +1647,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
p.setComment(s.Doc)
p.expr(s.Name)
if s.TypeParams != nil {
p.parameters(s.TypeParams, true)
p.parameters(s.TypeParams, typeTParam)
}
if n == 1 {
p.print(blank)
@ -1829,7 +1837,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
// FUNC is emitted).
startCol := p.out.Column - len("func ")
if d.Recv != nil {
p.parameters(d.Recv, false) // method: print receiver
p.parameters(d.Recv, funcParam) // method: print receiver
p.print(blank)
}
p.expr(d.Name)

View File

@ -64,3 +64,29 @@ type _ [P*T - T]struct{}
type _[
P *T,
] struct{}
// equivalent test cases for potentially ambiguous type parameter lists, except
// for function declarations there is no ambiguity (issue #51548)
func _[P *T]() {}
func _[P *T, _ any]() {}
func _[P *T]() {}
func _[P *T, _ any]() {}
func _[P T]() {}
func _[P T, _ any]() {}
func _[P *struct{}]() {}
func _[P *struct{}]() {}
func _[P []int]() {}
func _[P T]() {}
func _[P T]() {}
func _[P **T]() {}
func _[P *T]() {}
func _[P *T]() {}
func _[P **T]() {}
func _[P *T]() {}
func _[
P *T,
]() {
}

View File

@ -61,3 +61,28 @@ type _ [P * T - T]struct{}
type _[
P *T,
] struct{}
// equivalent test cases for potentially ambiguous type parameter lists, except
// for function declarations there is no ambiguity (issue #51548)
func _[P *T,]() {}
func _[P *T, _ any]() {}
func _[P (*T),]() {}
func _[P (*T), _ any]() {}
func _[P (T),]() {}
func _[P (T), _ any]() {}
func _[P *struct{}] () {}
func _[P (*struct{})] () {}
func _[P ([]int)] () {}
func _ [P(T)]() {}
func _ [P((T))]() {}
func _ [P * *T]() {}
func _ [P * T]() {}
func _ [P(*T)]() {}
func _ [P(**T)]() {}
func _ [P * T]() {}
func _[
P *T,
]() {}