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 <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/refactor/inline/falcon.go b/internal/refactor/inline/falcon.go
index 9ad57d7..9863e8d 100644
--- a/internal/refactor/inline/falcon.go
+++ b/internal/refactor/inline/falcon.go
@@ -610,10 +610,7 @@
 			// 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 08a4594..f3bc4db 100644
--- a/internal/refactor/inline/inline.go
+++ b/internal/refactor/inline/inline.go
@@ -1284,10 +1284,7 @@
 			// 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 58abc1e..8918977 100644
--- a/internal/refactor/inline/inline_test.go
+++ b/internal/refactor/inline/inline_test.go
@@ -382,6 +382,12 @@
 	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 6d8d3fa..98d654e 100644
--- a/internal/refactor/inline/util.go
+++ b/internal/refactor/inline/util.go
@@ -103,3 +103,17 @@
 	}
 	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},
+	}
+}