From: Robert Findley Date: Fri, 29 Oct 2021 22:06:15 +0000 (-0400) Subject: go/types: slice exprs to accept type sets with single underlying types X-Git-Tag: go1.18beta1~665 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=71e6ab8f958bf346f9e0b46c4a35310615360215;p=gostls13.git go/types: slice exprs to accept type sets with single underlying types This is a port of CL 357779 to go/types. A test error message was repositioned on the sliced operand. Change-Id: Ie775c128f70d9cb08a2eba54b8bc082134ec3200 Reviewed-on: https://go-review.googlesource.com/c/go/+/359876 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- diff --git a/src/go/types/index.go b/src/go/types/index.go index 613f6292e4..24c1812039 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -207,9 +207,14 @@ func (check *Checker) sliceExpr(x *operand, e *ast.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, _NonSliceableOperand, "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.Slice3 { check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") x.mode = invalid @@ -221,26 +226,26 @@ func (check *Checker) sliceExpr(x *operand, e *ast.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.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", 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/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index c4b0c212d2..3694b0ed00 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/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 */ ) }