summaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/syntax/printer.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-12-08 20:32:29 -0800
committerRobert Griesemer <gri@golang.org>2021-12-17 00:14:49 +0000
commit33a1a93a92804205eca89e2bb113ca68c1de5a4f (patch)
treead64468f900b3e4deac34a609c8b1cac6b20ecd4 /src/cmd/compile/internal/syntax/printer.go
parent0c24038d22a83c0da5feb3d700b13445f47b24c9 (diff)
downloadgo-git-33a1a93a92804205eca89e2bb113ca68c1de5a4f.tar.gz
cmd/compile/internal/syntax: fix parsing of type parameter lists
The parser cannot distinguish a type parameter list of the form [P *T ] or [P (T)] where T is not a type literal from an array length specification P*T (product) or P(T) (constant-valued function call) and thus interprets these forms as the start of array types. This ambiguity must be resolved explicitly by placing *T inside an interface, adding a trailing comma, or by leaving parentheses away where possible. This CL adjusts the parser such that these forms are interpreted as (the beginning) of type parameter lists if the token after P*T or P(T) is a comma, or if T is a type literal. This CL also adjusts the printer to print a comma if necessary to avoid this ambiguity, and adds additional printer tests. Fixes #49482 Change-Id: I36328e2a7d9439c39ba0349837c445542549e84e Reviewed-on: https://go-review.googlesource.com/c/go/+/370774 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/syntax/printer.go')
-rw-r--r--src/cmd/compile/internal/syntax/printer.go55
1 files changed, 30 insertions, 25 deletions
diff --git a/src/cmd/compile/internal/syntax/printer.go b/src/cmd/compile/internal/syntax/printer.go
index c8d31799af..11190ab287 100644
--- a/src/cmd/compile/internal/syntax/printer.go
+++ b/src/cmd/compile/internal/syntax/printer.go
@@ -666,9 +666,7 @@ func (p *printer) printRawNode(n Node) {
}
p.print(n.Name)
if n.TParamList != nil {
- p.print(_Lbrack)
- p.printFieldList(n.TParamList, nil, _Comma)
- p.print(_Rbrack)
+ p.printParameterList(n.TParamList, true)
}
p.print(blank)
if n.Alias {
@@ -700,9 +698,7 @@ func (p *printer) printRawNode(n Node) {
}
p.print(n.Name)
if n.TParamList != nil {
- p.print(_Lbrack)
- p.printFieldList(n.TParamList, nil, _Comma)
- p.print(_Rbrack)
+ p.printParameterList(n.TParamList, true)
}
p.printSignature(n.Type)
if n.Body != nil {
@@ -887,38 +883,47 @@ func (p *printer) printDeclList(list []Decl) {
}
func (p *printer) printSignature(sig *FuncType) {
- p.printParameterList(sig.ParamList)
+ p.printParameterList(sig.ParamList, false)
if list := sig.ResultList; list != nil {
p.print(blank)
if len(list) == 1 && list[0].Name == nil {
p.printNode(list[0].Type)
} else {
- p.printParameterList(list)
+ p.printParameterList(list, false)
}
}
}
-func (p *printer) printParameterList(list []*Field) {
- p.print(_Lparen)
- if len(list) > 0 {
- for i, f := range list {
- if i > 0 {
- p.print(_Comma, blank)
- }
- if f.Name != nil {
- p.printNode(f.Name)
- if i+1 < len(list) {
- f1 := list[i+1]
- if f1.Name != nil && f1.Type == f.Type {
- continue // no need to print type
- }
+func (p *printer) printParameterList(list []*Field, types bool) {
+ open, close := _Lparen, _Rparen
+ if types {
+ open, close = _Lbrack, _Rbrack
+ }
+ p.print(open)
+ for i, f := range list {
+ if i > 0 {
+ p.print(_Comma, blank)
+ }
+ if f.Name != nil {
+ p.printNode(f.Name)
+ if i+1 < len(list) {
+ f1 := list[i+1]
+ if f1.Name != nil && f1.Type == f.Type {
+ continue // no need to print type
}
- p.print(blank)
}
- p.printNode(f.Type)
+ p.print(blank)
+ }
+ p.printNode(unparen(f.Type)) // no need for (extra) parentheses around parameter types
+ }
+ // A type parameter list [P *T] where T is not a type literal requires a comma as in [P *T,]
+ // so that it's not parsed as [P*T].
+ if types && len(list) == 1 {
+ if t, _ := list[0].Type.(*Operation); t != nil && t.Op == Mul && t.Y == nil && !isTypeLit(t.X) {
+ p.print(_Comma)
}
}
- p.print(_Rparen)
+ p.print(close)
}
func (p *printer) printStmtList(list []Stmt, braces bool) {