]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: add parentheses to properly bind <- in ChanOf’s string
authorAlexander Klauer <Alexander.Klauer@googlemail.com>
Mon, 29 Jun 2020 16:02:07 +0000 (16:02 +0000)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Fri, 14 Aug 2020 22:58:36 +0000 (22:58 +0000)
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 <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>

src/reflect/all_test.go
src/reflect/type.go

index 63f6a92157229fce5cfa3eb7e646308b5ba21a26..6b31568bb9e9cd7dc3e464a7c9d3090a7dc2fc2f 100644 (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) {
index 38b1283d42a52c2bb638c1304a744fa2c5ad85f7..44c96fea8282a91cd6bb68fdc178dd7d8f140770 100644 (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))