reflect: add parentheses to properly bind <- in ChanOf’s string

Adds parentheses so as to properly bind <- to the right most
channel.
This meant that previously given:

   ChanOf(<-chan T)

it would mistakenly try to look up the type as

    chan <-chan T

instead of

    chan (<-chan T)

Fixes #39897

Change-Id: I8564916055f5fadde3382e41fe8820a1071e5f13
GitHub-Last-Rev: f8f2abe8d4
GitHub-Pull-Request: golang/go#39898
Reviewed-on: https://go-review.googlesource.com/c/go/+/240280
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Alexander Klauer 2020-06-29 16:02:07 +00:00 committed by Emmanuel Odeke
parent 32a84c99e1
commit 407bf0ca67
2 changed files with 26 additions and 2 deletions

View File

@ -74,6 +74,10 @@ var typeTests = []pair{
{struct{ x ([]int8) }{}, "[]int8"},
{struct{ x (map[string]int32) }{}, "map[string]int32"},
{struct{ x (chan<- string) }{}, "chan<- string"},
{struct{ x (chan<- chan string) }{}, "chan<- chan string"},
{struct{ x (chan<- <-chan string) }{}, "chan<- <-chan string"},
{struct{ x (<-chan <-chan string) }{}, "<-chan <-chan string"},
{struct{ x (chan (<-chan string)) }{}, "chan (<-chan string)"},
{struct {
x struct {
c chan *int32
@ -5491,6 +5495,18 @@ func TestChanOf(t *testing.T) {
// check that type already in binary is found
type T1 int
checkSameType(t, ChanOf(BothDir, TypeOf(T1(1))), (chan T1)(nil))
// Check arrow token association in undefined chan types.
var left chan<- chan T
var right chan (<-chan T)
tLeft := ChanOf(SendDir, ChanOf(BothDir, TypeOf(T(""))))
tRight := ChanOf(BothDir, ChanOf(RecvDir, TypeOf(T(""))))
if tLeft != TypeOf(left) {
t.Errorf("chan<-chan: have %s, want %T", tLeft, left)
}
if tRight != TypeOf(right) {
t.Errorf("chan<-chan: have %s, want %T", tRight, right)
}
}
func TestChanOfDir(t *testing.T) {

View File

@ -1789,7 +1789,6 @@ func ChanOf(dir ChanDir, t Type) Type {
}
// Look in known types.
// TODO: Precedence when constructing string.
var s string
switch dir {
default:
@ -1799,7 +1798,16 @@ func ChanOf(dir ChanDir, t Type) Type {
case RecvDir:
s = "<-chan " + typ.String()
case BothDir:
s = "chan " + typ.String()
typeStr := typ.String()
if typeStr[0] == '<' {
// typ is recv chan, need parentheses as "<-" associates with leftmost
// chan possible, see:
// * https://golang.org/ref/spec#Channel_types
// * https://github.com/golang/go/issues/39897
s = "chan (" + typeStr + ")"
} else {
s = "chan " + typeStr
}
}
for _, tt := range typesByString(s) {
ch := (*chanType)(unsafe.Pointer(tt))