go/types: implement indexing of generic types

Change-Id: I88a488d9d279b1029dd8086ea1befaa7b5733df6
This commit is contained in:
Robert Griesemer 2020-01-08 09:09:30 -08:00
parent d2fce6bc64
commit 1a2a175a8e
2 changed files with 57 additions and 0 deletions

View File

@ -1361,6 +1361,43 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
x.typ = typ.elem
x.expr = e
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:
e = t.elem
}
if e == nil || elem != nil && e != elem {
elem = nil
break
}
elem = e
}
if elem != nil {
valid = true
x.mode = variable
x.typ = elem
}
}
}
if !valid {
@ -1422,6 +1459,10 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *Slice:
valid = true
// x.typ doesn't change
case *TypeParam:
check.errorf(x.pos(), "generic slice expressions not yet implemented")
goto Error
}
if !valid {

View File

@ -79,6 +79,22 @@ func f3(type A, B, C)(A, struct{x B}, func(A, struct{x B}, *C)) int
var _ = f3(int, rune, bool)(1, struct{x rune}{}, nil)
// indexing
func _(type T) (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _(type T interface{ type int }) (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _(type T interface{ type string }) (x T, i int) { _ = x[i] }
func _(type T interface{ type []int }) (x T, i int) { _ = x[i] }
func _(type T interface{ type [10]int, *[20]int, map[string]int }) (x T, i int) { _ = x[i] }
func _(type T interface{ type string, []byte }) (x T, i int) { _ = x[i] }
func _(type T interface{ type []int, [1]rune }) (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _(type T interface{ type string, []rune }) (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
// slicing
// TODO(gri) implement this
func _(type T interface{ type string }) (x T, i, j, k int) { _ = x /* ERROR not yet implemented */ [i:j:k] }
// len/cap built-ins
func _(type T)(x T) { _ = len(x /* ERROR invalid argument */ ) }