From 407bf0ca67200463cdd451937623078e0240335e Mon Sep 17 00:00:00 2001 From: Alexander Klauer Date: Mon, 29 Jun 2020 16:02:07 +0000 Subject: [PATCH] =?utf8?q?reflect:=20add=20parentheses=20to=20properly=20b?= =?utf8?q?ind=20<-=20in=20ChanOf=E2=80=99s=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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: f8f2abe8d4c9e3d1414c89cadca8a16ce5cdeab9 GitHub-Pull-Request: golang/go#39898 Reviewed-on: https://go-review.googlesource.com/c/go/+/240280 Reviewed-by: Emmanuel Odeke Reviewed-by: Keith Randall Run-TryBot: Emmanuel Odeke TryBot-Result: Gobot Gobot --- src/reflect/all_test.go | 16 ++++++++++++++++ src/reflect/type.go | 12 ++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 63f6a92157..6b31568bb9 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -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) { diff --git a/src/reflect/type.go b/src/reflect/type.go index 38b1283d42..44c96fea82 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -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)) -- 2.50.0