aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/stmt.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/types2/stmt.go')
-rw-r--r--src/cmd/compile/internal/types2/stmt.go37
1 files changed, 5 insertions, 32 deletions
diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go
index ad8efa91f8..7865c2d4f4 100644
--- a/src/cmd/compile/internal/types2/stmt.go
+++ b/src/cmd/compile/internal/types2/stmt.go
@@ -789,9 +789,9 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// determine key/value types
var key, val Type
if x.mode != invalid {
+ // Ranging over a type parameter is permitted if it has a structural type.
typ := optype(x.typ)
if _, ok := typ.(*Chan); ok && sValue != nil {
- // TODO(gri) this also needs to happen for channels in generic variables
check.softErrorf(sValue, "range over %s permits only one iteration variable", &x)
// ok to continue
}
@@ -900,7 +900,7 @@ func isVarName(x syntax.Expr) bool {
// variables are used or present; this matters if we range over a generic
// type where not all keys or values are of the same type.
func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) {
- switch typ := typ.(type) {
+ switch typ := arrayPtrDeref(typ).(type) {
case *Basic:
if isString(typ) {
return Typ[Int], universeRune, "" // use 'rune' name
@@ -909,10 +909,6 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) {
return Typ[Int], typ.elem, ""
case *Slice:
return Typ[Int], typ.elem, ""
- case *Pointer:
- if typ := asArray(typ.base); typ != nil {
- return Typ[Int], typ.elem, ""
- }
case *Map:
return typ.key, typ.elem, ""
case *Chan:
@@ -921,32 +917,9 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) {
msg = "receive from send-only channel"
}
return typ.elem, Typ[Invalid], msg
- case *TypeParam:
- first := true
- var key, val Type
- var msg string
- typ.underIs(func(t Type) bool {
- k, v, m := rangeKeyVal(t, wantKey, wantVal)
- if k == nil || m != "" {
- key, val, msg = k, v, m
- return false
- }
- if first {
- key, val, msg = k, v, m
- first = false
- return true
- }
- if wantKey && !Identical(key, k) {
- key, val, msg = nil, nil, "all possible values must have the same key type"
- return false
- }
- if wantVal && !Identical(val, v) {
- key, val, msg = nil, nil, "all possible values must have the same element type"
- return false
- }
- return true
- })
- return key, val, msg
+ case *top:
+ // we have a type parameter with no structural type
+ return nil, nil, "no structural type"
}
return nil, nil, ""
}