diff options
author | Robert Griesemer <gri@golang.org> | 2021-12-08 20:32:29 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2021-12-17 00:14:49 +0000 |
commit | 33a1a93a92804205eca89e2bb113ca68c1de5a4f (patch) | |
tree | ad64468f900b3e4deac34a609c8b1cac6b20ecd4 /src/cmd/compile/internal/syntax/printer.go | |
parent | 0c24038d22a83c0da5feb3d700b13445f47b24c9 (diff) | |
download | go-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.go | 55 |
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) { |