]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer: don't print unnecesary commas for func type param lists
authorRobert Findley <rfindley@google.com>
Tue, 8 Mar 2022 21:43:47 +0000 (16:43 -0500)
committerRobert Findley <rfindley@google.com>
Tue, 8 Mar 2022 22:23:42 +0000 (22:23 +0000)
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>

src/go/printer/nodes.go
src/go/printer/testdata/generics.golden
src/go/printer/testdata/generics.input

index f2170dbc4f31c1ecd57660dd93867729001ab1c8..9a09d58eb2c8d6ce2a1e7bc0c2b38015f9ea37fa 100644 (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)
index 4fac2c9c580b159d0a61c8e01859962e9c5d2a7e..c3a7df83725205afc4cec95cd73f57d477fbf981 100644 (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,
+]() {
+}
index fde9d32ef04844f1b46bfb229776932f29e21f7d..66e1554f7ffb8359838be524849721a9b18c2e09 100644 (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,
+]() {}