diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 8fc20c8d07..992f4e86dc 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -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 { diff --git a/src/go/types/testdata/typeparams.go2 b/src/go/types/testdata/typeparams.go2 index 87c9ca7b11..9f32011bcd 100644 --- a/src/go/types/testdata/typeparams.go2 +++ b/src/go/types/testdata/typeparams.go2 @@ -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 */ ) }