]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: slice exprs to accept type sets with single underlying types
authorRobert Findley <rfindley@google.com>
Fri, 29 Oct 2021 22:06:15 +0000 (18:06 -0400)
committerRobert Findley <rfindley@google.com>
Fri, 29 Oct 2021 22:27:54 +0000 (22:27 +0000)
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 <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/index.go
src/go/types/testdata/check/typeparams.go2

index 613f6292e49934c6aca0902262104cfb7494ed9a..24c1812039f63a7b34e41723411a0fb2ba70f665 100644 (file)
@@ -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:
index c4b0c212d28cc8c4115fcae2e8e0c4c83b819d97..3694b0ed008a2c50c0d846bc1d9610458ccca440 100644 (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 */ ) }