]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/printer: parenthesize type in <-((<-chan int)(nil))
authorAlan Donovan <adonovan@google.com>
Wed, 4 Oct 2023 14:26:17 +0000 (10:26 -0400)
committerGopher Robot <gobot@golang.org>
Wed, 4 Oct 2023 16:05:21 +0000 (16:05 +0000)
When printing synthetic syntax (not created by the parser),
the tree for <-((<-chan int)(nil)) without any ParenExpr nodes
was misprinted so that it was parsed back as a receive of
a receive. This changes emits parens around the channel type.

Fixes #63362

Change-Id: I2041ced224f0bca001cee5d37f7a127265d21020
Reviewed-on: https://go-review.googlesource.com/c/go/+/532556
Auto-Submit: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
src/go/printer/nodes.go
src/go/printer/printer_test.go

index 97c2cab0f840aed480ae5cd72c5085a078106d6f..0a693b6667ac314fdcf486d01eb16fefba7784c4 100644 (file)
@@ -974,15 +974,24 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                if len(x.Args) > 1 {
                        depth++
                }
-               var wasIndented bool
-               if _, ok := x.Fun.(*ast.FuncType); ok {
-                       // conversions to literal function types require parentheses around the type
+
+               // Conversions to literal function types or <-chan
+               // types require parentheses around the type.
+               paren := false
+               switch t := x.Fun.(type) {
+               case *ast.FuncType:
+                       paren = true
+               case *ast.ChanType:
+                       paren = t.Dir == ast.RECV
+               }
+               if paren {
                        p.print(token.LPAREN)
-                       wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
+               }
+               wasIndented := p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
+               if paren {
                        p.print(token.RPAREN)
-               } else {
-                       wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
                }
+
                p.setPos(x.Lparen)
                p.print(token.LPAREN)
                if x.Ellipsis.IsValid() {
index 3a8ce6043164848555cb12b7d985346badfaf1c3..8e78bc640e1a230541569d079aff74a246c0c6ca 100644 (file)
@@ -604,6 +604,29 @@ func f()
        }
 }
 
+// TestChanType tests that the tree for <-(<-chan int), without
+// ParenExpr, is correctly formatted with parens.
+// Test case for issue #63362.
+func TestChanType(t *testing.T) {
+       expr := &ast.UnaryExpr{
+               Op: token.ARROW,
+               X: &ast.CallExpr{
+                       Fun: &ast.ChanType{
+                               Dir:   ast.RECV,
+                               Value: &ast.Ident{Name: "int"},
+                       },
+                       Args: []ast.Expr{&ast.Ident{Name: "nil"}},
+               },
+       }
+       var buf bytes.Buffer
+       if err := Fprint(&buf, fset, expr); err != nil {
+               t.Fatal(err)
+       }
+       if got, want := buf.String(), `<-(<-chan int)(nil)`; got != want {
+               t.Fatalf("got:\n%s\nwant:\n%s\n", got, want)
+       }
+}
+
 type limitWriter struct {
        remaining int
        errCount  int