diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 47a5e50f627..62f49b95dab 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -207,9 +207,14 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch u := singleUnder(x.typ).(type) { + case nil: + check.errorf(x, invalidOp+"cannot slice %s: type set has no single underlying type", x) + x.mode = invalid + return + case *Basic: - if isString(typ) { + if isString(u) { if e.Full { check.error(x, invalidOp+"3-index slice of string") x.mode = invalid @@ -221,26 +226,26 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { } // spec: "For untyped string operands the result // is a non-constant value of type string." - if typ.kind == UntypedString { + if u.kind == UntypedString { x.typ = Typ[String] } } case *Array: valid = true - length = typ.len + length = u.len if x.mode != variable { check.errorf(x, invalidOp+"%s (slice of unaddressable value)", x) x.mode = invalid return } - x.typ = &Slice{elem: typ.elem} + x.typ = &Slice{elem: u.elem} case *Pointer: - if typ := asArray(typ.base); typ != nil { + if u := asArray(u.base); u != nil { valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} + length = u.len + x.typ = &Slice{elem: u.elem} } case *Slice: diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index d1f07a20d4f..1200a6e8741 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -123,6 +123,11 @@ func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +type myByte1 []byte +type myByte2 []byte +func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } +func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no single underlying type */ i:j:k] } + // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) }