diff options
author | Robert Griesemer <gri@golang.org> | 2021-07-09 17:12:07 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2021-07-14 23:33:43 +0000 |
commit | ff33d3dc3a47a4eed17728b8460de4572198cec3 (patch) | |
tree | 46f509e94483cc1f04e6aa5cf9fd34fe7146e1fc /src/cmd/compile/internal/types2/expr.go | |
parent | e3e6cd30221185d6e4fa76f109f96fdede580729 (diff) | |
download | go-ff33d3dc3a47a4eed17728b8460de4572198cec3.tar.gz go-ff33d3dc3a47a4eed17728b8460de4572198cec3.zip |
[dev.typeparams] cmd/compile/internal/types2: implement <-ch where ch is of type parameter type
For #43671
Change-Id: I7db4b3886fab44ec0de7c0935e0ab21c26e3335c
Reviewed-on: https://go-review.googlesource.com/c/go/+/333709
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types2/expr.go')
-rw-r--r-- | src/cmd/compile/internal/types2/expr.go | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index bd35417c64..d4425a2bfd 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -157,6 +157,14 @@ var op2str2 = [...]string{ syntax.Shl: "shift", } +func underIs(typ Type, f func(Type) bool) bool { + u := under(typ) + if tpar, _ := u.(*TypeParam); tpar != nil { + return tpar.underIs(f) + } + return f(u) +} + func (check *Checker) unary(x *operand, e *syntax.Operation) { check.expr(x, e.X) if x.mode == invalid { @@ -177,19 +185,29 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return case syntax.Recv: - typ := asChan(x.typ) - if typ == nil { - check.errorf(x, invalidOp+"cannot receive from non-channel %s", x) - x.mode = invalid - return - } - if typ.dir == SendOnly { - check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x) + var elem Type + if !underIs(x.typ, func(u Type) bool { + ch, _ := u.(*Chan) + if ch == nil { + check.errorf(x, invalidOp+"cannot receive from non-channel %s", x) + return false + } + if ch.dir == SendOnly { + check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x) + return false + } + if elem != nil && !Identical(ch.elem, elem) { + check.errorf(x, invalidOp+"channels of %s must have the same element type", x) + return false + } + elem = ch.elem + return true + }) { x.mode = invalid return } x.mode = commaok - x.typ = typ.elem + x.typ = elem check.hasCallOrRecv = true return } |