cmd/compile/internal/types2: slice exprs to accept type sets with single underlying types
Change-Id: Ib9bd08ab6153129aaf8b77b41fc6ea302d0c1589
Reviewed-on: https://go-review.googlesource.com/c/go/+/357779
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go
index 47a5e50..62f49b9 100644
--- a/src/cmd/compile/internal/types2/index.go
+++ b/src/cmd/compile/internal/types2/index.go
@@ -207,9 +207,14 @@
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 @@
}
// 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 d1f07a2..1200a6e 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{ ~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 */ ) }