diff options
author | Rob Findley <rfindley@google.com> | 2021-07-16 20:16:27 -0400 |
---|---|---|
committer | Robert Findley <rfindley@google.com> | 2021-07-19 17:08:29 +0000 |
commit | d6d7f8458e9e4360d7b0a4e42c5c850ae27bac8d (patch) | |
tree | afb1fe4e76d572bdcc3d6fa4c17dfaf4cb3075e2 /src/go/types/expr.go | |
parent | 796ac6d5f24f725794a3620d767d30c52f232a60 (diff) | |
download | go-d6d7f8458e9e4360d7b0a4e42c5c850ae27bac8d.tar.gz go-d6d7f8458e9e4360d7b0a4e42c5c850ae27bac8d.zip |
[dev.typeparams] go/types: implement <-ch where ch is of type parameter type
This is a port of CL 333709 to go/types, adjusted for the different
error API.
Fixes #43671
Change-Id: Ifd340149bfbcabe401cec74398cb83f2ae812e51
Reviewed-on: https://go-review.googlesource.com/c/go/+/335075
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/go/types/expr.go')
-rw-r--r-- | src/go/types/expr.go | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 46f6e33463..751a360890 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -144,6 +144,14 @@ var op2str2 = [...]string{ token.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) +} + // The unary expression e may be nil. It's passed in for better error messages only. func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { check.expr(x, e.X) @@ -164,19 +172,29 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return case token.ARROW: - typ := asChan(x.typ) - if typ == nil { - check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) - x.mode = invalid - return - } - if typ.dir == SendOnly { - check.invalidOp(x, _InvalidReceive, "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.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) + return false + } + if ch.dir == SendOnly { + check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x) + return false + } + if elem != nil && !Identical(ch.elem, elem) { + check.invalidOp(x, _Todo, "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 } |