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>
This commit is contained in:
Robert Griesemer 2021-10-21 16:17:07 -07:00
parent c526cf8c1e
commit 12e4404a0a
2 changed files with 18 additions and 8 deletions

View File

@ -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:

View File

@ -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 */ ) }