1
0
mirror of https://github.com/golang/go synced 2024-11-17 20:04:47 -07:00

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 <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Robert Findley 2021-10-29 18:06:15 -04:00
parent 02bd226b8a
commit 71e6ab8f95
2 changed files with 18 additions and 8 deletions

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

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