From 0c64ebce7e7007615aba58a19be07372f0febe69 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 4 Oct 2023 10:26:17 -0400 Subject: [PATCH] go/printer: parenthesize type in <-((<-chan int)(nil)) 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 Run-TryBot: Robert Griesemer LUCI-TryBot-Result: Go LUCI TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- src/go/printer/nodes.go | 25 +++++++++++++++++-------- src/go/printer/printer_test.go | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 97c2cab0f8..0a693b6667 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -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 - p.print(token.LPAREN) - wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth) - p.print(token.RPAREN) - } else { - wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth) + + // 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) + if paren { + p.print(token.RPAREN) + } + p.setPos(x.Lparen) p.print(token.LPAREN) if x.Ellipsis.IsValid() { diff --git a/src/go/printer/printer_test.go b/src/go/printer/printer_test.go index 3a8ce60431..8e78bc640e 100644 --- a/src/go/printer/printer_test.go +++ b/src/go/printer/printer_test.go @@ -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