mirror of https://github.com/golang/go.git
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
This commit is contained in:
parent
1a2a175a8e
commit
3c2505cae9
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue