From 3c2505cae9c51d421cb1402bcc372d7176dfcf18 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Jan 2020 09:31:22 -0800 Subject: [PATCH] go/types: use Interface.is for generic variable indexing/len/cap (cleanup) Interface.is already takes care of iterating through all types of a generic type bound; use it instead of writing custom loops each time. Change-Id: Ie0f91b27e5a7b65ea85a8c3847a954db1e9f24fe --- src/go/types/builtins.go | 34 ++++++++++-------------- src/go/types/expr.go | 57 +++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 50 deletions(-) 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 } }