From 2be977ecc58df8383c28bc0587b6db6af20638d5 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 4 Oct 2023 11:06:14 -0400 Subject: [PATCH] internal/refactor/inline: work around channel type misformatting This change adds parens around the type in T(x) conversions where T is a receive-only channel type, as previously it would be misformatted as a receive of a receive. Updates golang/go#63362 Change-Id: I935b5598d4bc3ea57dd52964e8b02005f5e6ef72 Reviewed-on: https://go-review.googlesource.com/c/tools/+/532576 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- internal/refactor/inline/falcon.go | 5 +---- internal/refactor/inline/inline.go | 5 +---- internal/refactor/inline/inline_test.go | 6 ++++++ internal/refactor/inline/util.go | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/internal/refactor/inline/falcon.go b/internal/refactor/inline/falcon.go index 9ad57d727..9863e8dbc 100644 --- a/internal/refactor/inline/falcon.go +++ b/internal/refactor/inline/falcon.go @@ -610,10 +610,7 @@ func (st *falconState) expr(e ast.Expr) (res any) { // = types.TypeAndValue | as // Possible "value out of range". kX := st.expr(e.Args[0]) if kX != nil && isBasic(tv.Type, types.IsConstType) { - conv := &ast.CallExpr{ - Fun: makeIdent(st.typename(tv.Type)), - Args: []ast.Expr{st.toExpr(kX)}, - } + conv := convert(makeIdent(st.typename(tv.Type)), st.toExpr(kX)) if is[ast.Expr](kX) { st.emit(conv) } diff --git a/internal/refactor/inline/inline.go b/internal/refactor/inline/inline.go index 08a4594ae..f3bc4dbf6 100644 --- a/internal/refactor/inline/inline.go +++ b/internal/refactor/inline/inline.go @@ -1284,10 +1284,7 @@ next: // a binding decl or when using the literalization // strategy. if len(param.info.Refs) > 0 && !trivialConversion(args[i].typ, params[i].obj) { - arg.expr = &ast.CallExpr{ - Fun: params[i].fieldType, // formatter adds parens as needed - Args: []ast.Expr{arg.expr}, - } + arg.expr = convert(params[i].fieldType, arg.expr) logf("param %q: adding explicit %s -> %s conversion around argument", param.info.Name, args[i].typ, params[i].obj.Type()) } diff --git a/internal/refactor/inline/inline_test.go b/internal/refactor/inline/inline_test.go index 58abc1eda..891897704 100644 --- a/internal/refactor/inline/inline_test.go +++ b/internal/refactor/inline/inline_test.go @@ -382,6 +382,12 @@ func TestBasics(t *testing.T) { print(s, s, 0, 0) }`, }, + { + "Workaround for T(x) misformatting (#63362).", + `func f(ch <-chan int) { <-ch }`, + `func _(ch chan int) { f(ch) }`, + `func _(ch chan int) { <-(<-chan int)(ch) }`, + }, }) } diff --git a/internal/refactor/inline/util.go b/internal/refactor/inline/util.go index 6d8d3fac0..98d654eeb 100644 --- a/internal/refactor/inline/util.go +++ b/internal/refactor/inline/util.go @@ -103,3 +103,17 @@ func intersects[K comparable, T1, T2 any](x map[K]T1, y map[K]T2) bool { } return false } + +// convert returns syntax for the conversion T(x). +func convert(T, x ast.Expr) *ast.CallExpr { + // The formatter generally adds parens as needed, + // but before go1.22 it had a bug (#63362) for + // channel types that requires this workaround. + if ch, ok := T.(*ast.ChanType); ok && ch.Dir == ast.RECV { + T = &ast.ParenExpr{X: T} + } + return &ast.CallExpr{ + Fun: T, + Args: []ast.Expr{x}, + } +}