aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/expr.go
diff options
context:
space:
mode:
authorRob Findley <rfindley@google.com>2021-07-16 20:16:27 -0400
committerRobert Findley <rfindley@google.com>2021-07-19 17:08:29 +0000
commitd6d7f8458e9e4360d7b0a4e42c5c850ae27bac8d (patch)
treeafb1fe4e76d572bdcc3d6fa4c17dfaf4cb3075e2 /src/go/types/expr.go
parent796ac6d5f24f725794a3620d767d30c52f232a60 (diff)
downloadgo-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.go36
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
}