diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 1285ff178b..e2ef8ea09f 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -176,28 +176,22 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } case *TypeParam: - if types := t.Interface().allTypes; len(types) > 0 { - mode = value // assume we're ok - L: - for _, t := range types { - switch t.(type) { - case *Basic: - if !isString(t) || id != _Len { - mode = invalid - break L - } - case *Array, *Slice, *Chan: - // ok - case *Map: - if id != _Len { - mode = invalid - break L - } - default: - mode = invalid - break L + if t.Interface().is(func(t Type) bool { + switch t.(type) { + case *Basic: + if isString(t) && id == _Len { + return true + } + case *Array, *Slice, *Chan: + return true + case *Map: + if id == _Len { + return true } } + return false + }) { + mode = value } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 992f4e86dc..89eecebfb6 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1363,40 +1363,37 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { return expression case *TypeParam: - if types := typ.Interface().allTypes; len(types) > 0 { - // A generic variable can be indexed if all types - // in its type bound support indexing and have the - // same element type. - var elem Type - for _, t := range types { - var e Type - switch t := t.(type) { - case *Basic: - if isString(t) { - e = universeByte - } - case *Array: - e = t.elem - case *Pointer: - if t, _ := t.base.Underlying().(*Array); t != nil { - e = t.elem - } - case *Slice: - e = t.elem - case *Map: + // A generic variable can be indexed if all types + // in its type bound support indexing and have the + // same element type. + var elem Type + if typ.Interface().is(func(t Type) bool { + var e Type + switch t := t.(type) { + case *Basic: + if isString(t) { + e = universeByte + } + case *Array: + e = t.elem + case *Pointer: + if t, _ := t.base.Underlying().(*Array); t != nil { e = t.elem } - if e == nil || elem != nil && e != elem { - elem = nil - break - } + case *Slice: + e = t.elem + case *Map: + e = t.elem + } + if e != nil && (e == elem || elem == nil) { elem = e + return true } - if elem != nil { - valid = true - x.mode = variable - x.typ = elem - } + return false + }) { + valid = true + x.mode = variable + x.typ = elem } }