cmd/compile: implement slice-to-array conversions

The conversion T(x) is implemented as *(*T)(x). Accordingly, runtime
panic messages for (*T)(x) are made more general.

Fixes #46505.

Change-Id: I76317c0878b6a5908299506d392eed50d7ef6523
Reviewed-on: https://go-review.googlesource.com/c/go/+/430415
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Jenny Rakoczy <jenny@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Matthew Dempsky 2022-09-12 13:01:57 -07:00
parent 29153be757
commit ceffdc8545
15 changed files with 210 additions and 148 deletions

View File

@ -126,6 +126,10 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
case ir.OITAB, ir.OIDATA, ir.OSPTR:
n := n.(*ir.UnaryExpr)
e.expr(k, n.X)
case ir.OSLICE2ARR:
// Converting a slice to array is effectively a deref.
n := n.(*ir.ConvExpr)
e.expr(k.deref(n, "slice-to-array"), n.X)
case ir.OSLICE2ARRPTR:
// the slice pointer flows directly to the result
n := n.(*ir.ConvExpr)

View File

@ -289,7 +289,7 @@ func (n *ConvExpr) SetOp(op Op) {
switch op {
default:
panic(n.no("SetOp " + op.String()))
case OCONV, OCONVIFACE, OCONVIDATA, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARRPTR:
case OCONV, OCONVIFACE, OCONVIDATA, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARR, OSLICE2ARRPTR:
n.op = op
}
}

View File

@ -208,6 +208,7 @@ var OpPrec = []int{
OPRINT: 8,
ORUNESTR: 8,
OSIZEOF: 8,
OSLICE2ARR: 8,
OSLICE2ARRPTR: 8,
OSTR2BYTES: 8,
OSTR2RUNES: 8,
@ -753,6 +754,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
OSTR2BYTES,
OSTR2RUNES,
ORUNESTR,
OSLICE2ARR,
OSLICE2ARRPTR:
n := n.(*ConvExpr)
if n.Type() == nil || n.Type().Sym() == nil {

View File

@ -134,6 +134,7 @@ const (
OSTR2BYTES // Type(X) (Type is []byte, X is a string)
OSTR2BYTESTMP // Type(X) (Type is []byte, X is a string, ephemeral)
OSTR2RUNES // Type(X) (Type is []rune, X is a string)
OSLICE2ARR // Type(X) (Type is [N]T, X is a []T)
OSLICE2ARRPTR // Type(X) (Type is *[N]T, X is a []T)
// X = Y or (if Def=true) X := Y
// If Def, then Init includes a DCL node for X.

View File

@ -28,145 +28,146 @@ func _() {
_ = x[OSTR2BYTES-17]
_ = x[OSTR2BYTESTMP-18]
_ = x[OSTR2RUNES-19]
_ = x[OSLICE2ARRPTR-20]
_ = x[OAS-21]
_ = x[OAS2-22]
_ = x[OAS2DOTTYPE-23]
_ = x[OAS2FUNC-24]
_ = x[OAS2MAPR-25]
_ = x[OAS2RECV-26]
_ = x[OASOP-27]
_ = x[OCALL-28]
_ = x[OCALLFUNC-29]
_ = x[OCALLMETH-30]
_ = x[OCALLINTER-31]
_ = x[OCAP-32]
_ = x[OCLOSE-33]
_ = x[OCLOSURE-34]
_ = x[OCOMPLIT-35]
_ = x[OMAPLIT-36]
_ = x[OSTRUCTLIT-37]
_ = x[OARRAYLIT-38]
_ = x[OSLICELIT-39]
_ = x[OPTRLIT-40]
_ = x[OCONV-41]
_ = x[OCONVIFACE-42]
_ = x[OCONVIDATA-43]
_ = x[OCONVNOP-44]
_ = x[OCOPY-45]
_ = x[ODCL-46]
_ = x[ODCLFUNC-47]
_ = x[ODCLCONST-48]
_ = x[ODCLTYPE-49]
_ = x[ODELETE-50]
_ = x[ODOT-51]
_ = x[ODOTPTR-52]
_ = x[ODOTMETH-53]
_ = x[ODOTINTER-54]
_ = x[OXDOT-55]
_ = x[ODOTTYPE-56]
_ = x[ODOTTYPE2-57]
_ = x[OEQ-58]
_ = x[ONE-59]
_ = x[OLT-60]
_ = x[OLE-61]
_ = x[OGE-62]
_ = x[OGT-63]
_ = x[ODEREF-64]
_ = x[OINDEX-65]
_ = x[OINDEXMAP-66]
_ = x[OKEY-67]
_ = x[OSTRUCTKEY-68]
_ = x[OLEN-69]
_ = x[OMAKE-70]
_ = x[OMAKECHAN-71]
_ = x[OMAKEMAP-72]
_ = x[OMAKESLICE-73]
_ = x[OMAKESLICECOPY-74]
_ = x[OMUL-75]
_ = x[ODIV-76]
_ = x[OMOD-77]
_ = x[OLSH-78]
_ = x[ORSH-79]
_ = x[OAND-80]
_ = x[OANDNOT-81]
_ = x[ONEW-82]
_ = x[ONOT-83]
_ = x[OBITNOT-84]
_ = x[OPLUS-85]
_ = x[ONEG-86]
_ = x[OOROR-87]
_ = x[OPANIC-88]
_ = x[OPRINT-89]
_ = x[OPRINTN-90]
_ = x[OPAREN-91]
_ = x[OSEND-92]
_ = x[OSLICE-93]
_ = x[OSLICEARR-94]
_ = x[OSLICESTR-95]
_ = x[OSLICE3-96]
_ = x[OSLICE3ARR-97]
_ = x[OSLICEHEADER-98]
_ = x[OSTRINGHEADER-99]
_ = x[ORECOVER-100]
_ = x[ORECOVERFP-101]
_ = x[ORECV-102]
_ = x[ORUNESTR-103]
_ = x[OSELRECV2-104]
_ = x[OREAL-105]
_ = x[OIMAG-106]
_ = x[OCOMPLEX-107]
_ = x[OALIGNOF-108]
_ = x[OOFFSETOF-109]
_ = x[OSIZEOF-110]
_ = x[OUNSAFEADD-111]
_ = x[OUNSAFESLICE-112]
_ = x[OUNSAFESLICEDATA-113]
_ = x[OUNSAFESTRING-114]
_ = x[OUNSAFESTRINGDATA-115]
_ = x[OMETHEXPR-116]
_ = x[OMETHVALUE-117]
_ = x[OBLOCK-118]
_ = x[OBREAK-119]
_ = x[OCASE-120]
_ = x[OCONTINUE-121]
_ = x[ODEFER-122]
_ = x[OFALL-123]
_ = x[OFOR-124]
_ = x[OGOTO-125]
_ = x[OIF-126]
_ = x[OLABEL-127]
_ = x[OGO-128]
_ = x[ORANGE-129]
_ = x[ORETURN-130]
_ = x[OSELECT-131]
_ = x[OSWITCH-132]
_ = x[OTYPESW-133]
_ = x[OFUNCINST-134]
_ = x[OINLCALL-135]
_ = x[OEFACE-136]
_ = x[OITAB-137]
_ = x[OIDATA-138]
_ = x[OSPTR-139]
_ = x[OCFUNC-140]
_ = x[OCHECKNIL-141]
_ = x[ORESULT-142]
_ = x[OINLMARK-143]
_ = x[OLINKSYMOFFSET-144]
_ = x[OJUMPTABLE-145]
_ = x[ODYNAMICDOTTYPE-146]
_ = x[ODYNAMICDOTTYPE2-147]
_ = x[ODYNAMICTYPE-148]
_ = x[OTAILCALL-149]
_ = x[OGETG-150]
_ = x[OGETCALLERPC-151]
_ = x[OGETCALLERSP-152]
_ = x[OEND-153]
_ = x[OSLICE2ARR-20]
_ = x[OSLICE2ARRPTR-21]
_ = x[OAS-22]
_ = x[OAS2-23]
_ = x[OAS2DOTTYPE-24]
_ = x[OAS2FUNC-25]
_ = x[OAS2MAPR-26]
_ = x[OAS2RECV-27]
_ = x[OASOP-28]
_ = x[OCALL-29]
_ = x[OCALLFUNC-30]
_ = x[OCALLMETH-31]
_ = x[OCALLINTER-32]
_ = x[OCAP-33]
_ = x[OCLOSE-34]
_ = x[OCLOSURE-35]
_ = x[OCOMPLIT-36]
_ = x[OMAPLIT-37]
_ = x[OSTRUCTLIT-38]
_ = x[OARRAYLIT-39]
_ = x[OSLICELIT-40]
_ = x[OPTRLIT-41]
_ = x[OCONV-42]
_ = x[OCONVIFACE-43]
_ = x[OCONVIDATA-44]
_ = x[OCONVNOP-45]
_ = x[OCOPY-46]
_ = x[ODCL-47]
_ = x[ODCLFUNC-48]
_ = x[ODCLCONST-49]
_ = x[ODCLTYPE-50]
_ = x[ODELETE-51]
_ = x[ODOT-52]
_ = x[ODOTPTR-53]
_ = x[ODOTMETH-54]
_ = x[ODOTINTER-55]
_ = x[OXDOT-56]
_ = x[ODOTTYPE-57]
_ = x[ODOTTYPE2-58]
_ = x[OEQ-59]
_ = x[ONE-60]
_ = x[OLT-61]
_ = x[OLE-62]
_ = x[OGE-63]
_ = x[OGT-64]
_ = x[ODEREF-65]
_ = x[OINDEX-66]
_ = x[OINDEXMAP-67]
_ = x[OKEY-68]
_ = x[OSTRUCTKEY-69]
_ = x[OLEN-70]
_ = x[OMAKE-71]
_ = x[OMAKECHAN-72]
_ = x[OMAKEMAP-73]
_ = x[OMAKESLICE-74]
_ = x[OMAKESLICECOPY-75]
_ = x[OMUL-76]
_ = x[ODIV-77]
_ = x[OMOD-78]
_ = x[OLSH-79]
_ = x[ORSH-80]
_ = x[OAND-81]
_ = x[OANDNOT-82]
_ = x[ONEW-83]
_ = x[ONOT-84]
_ = x[OBITNOT-85]
_ = x[OPLUS-86]
_ = x[ONEG-87]
_ = x[OOROR-88]
_ = x[OPANIC-89]
_ = x[OPRINT-90]
_ = x[OPRINTN-91]
_ = x[OPAREN-92]
_ = x[OSEND-93]
_ = x[OSLICE-94]
_ = x[OSLICEARR-95]
_ = x[OSLICESTR-96]
_ = x[OSLICE3-97]
_ = x[OSLICE3ARR-98]
_ = x[OSLICEHEADER-99]
_ = x[OSTRINGHEADER-100]
_ = x[ORECOVER-101]
_ = x[ORECOVERFP-102]
_ = x[ORECV-103]
_ = x[ORUNESTR-104]
_ = x[OSELRECV2-105]
_ = x[OREAL-106]
_ = x[OIMAG-107]
_ = x[OCOMPLEX-108]
_ = x[OALIGNOF-109]
_ = x[OOFFSETOF-110]
_ = x[OSIZEOF-111]
_ = x[OUNSAFEADD-112]
_ = x[OUNSAFESLICE-113]
_ = x[OUNSAFESLICEDATA-114]
_ = x[OUNSAFESTRING-115]
_ = x[OUNSAFESTRINGDATA-116]
_ = x[OMETHEXPR-117]
_ = x[OMETHVALUE-118]
_ = x[OBLOCK-119]
_ = x[OBREAK-120]
_ = x[OCASE-121]
_ = x[OCONTINUE-122]
_ = x[ODEFER-123]
_ = x[OFALL-124]
_ = x[OFOR-125]
_ = x[OGOTO-126]
_ = x[OIF-127]
_ = x[OLABEL-128]
_ = x[OGO-129]
_ = x[ORANGE-130]
_ = x[ORETURN-131]
_ = x[OSELECT-132]
_ = x[OSWITCH-133]
_ = x[OTYPESW-134]
_ = x[OFUNCINST-135]
_ = x[OINLCALL-136]
_ = x[OEFACE-137]
_ = x[OITAB-138]
_ = x[OIDATA-139]
_ = x[OSPTR-140]
_ = x[OCFUNC-141]
_ = x[OCHECKNIL-142]
_ = x[ORESULT-143]
_ = x[OINLMARK-144]
_ = x[OLINKSYMOFFSET-145]
_ = x[OJUMPTABLE-146]
_ = x[ODYNAMICDOTTYPE-147]
_ = x[ODYNAMICDOTTYPE2-148]
_ = x[ODYNAMICTYPE-149]
_ = x[OTAILCALL-150]
_ = x[OGETG-151]
_ = x[OGETCALLERPC-152]
_ = x[OGETCALLERSP-153]
_ = x[OEND-154]
}
const _Op_name = "XXXNAMENONAMETYPELITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERSTRINGHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2REALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEUNSAFESLICEDATAUNSAFESTRINGUNSAFESTRINGDATAMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTINLCALLEFACEITABIDATASPTRCFUNCCHECKNILRESULTINLMARKLINKSYMOFFSETJUMPTABLEDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND"
const _Op_name = "XXXNAMENONAMETYPELITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERSTRINGHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2REALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEUNSAFESLICEDATAUNSAFESTRINGUNSAFESTRINGDATAMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTINLCALLEFACEITABIDATASPTRCFUNCCHECKNILRESULTINLMARKLINKSYMOFFSETJUMPTABLEDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND"
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 24, 27, 30, 33, 35, 38, 44, 48, 54, 60, 69, 81, 90, 99, 111, 120, 132, 134, 137, 147, 154, 161, 168, 172, 176, 184, 192, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 282, 289, 293, 296, 303, 311, 318, 324, 327, 333, 340, 348, 352, 359, 367, 369, 371, 373, 375, 377, 379, 384, 389, 397, 400, 409, 412, 416, 424, 431, 440, 453, 456, 459, 462, 465, 468, 471, 477, 480, 483, 489, 493, 496, 500, 505, 510, 516, 521, 525, 530, 538, 546, 552, 561, 572, 584, 591, 600, 604, 611, 619, 623, 627, 634, 641, 649, 655, 664, 675, 690, 702, 718, 726, 735, 740, 745, 749, 757, 762, 766, 769, 773, 775, 780, 782, 787, 793, 799, 805, 811, 819, 826, 831, 835, 840, 844, 849, 857, 863, 870, 883, 892, 906, 921, 932, 940, 944, 955, 966, 969}
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 24, 27, 30, 33, 35, 38, 44, 48, 54, 60, 69, 81, 90, 99, 111, 120, 129, 141, 143, 146, 156, 163, 170, 177, 181, 185, 193, 201, 210, 213, 218, 225, 232, 238, 247, 255, 263, 269, 273, 282, 291, 298, 302, 305, 312, 320, 327, 333, 336, 342, 349, 357, 361, 368, 376, 378, 380, 382, 384, 386, 388, 393, 398, 406, 409, 418, 421, 425, 433, 440, 449, 462, 465, 468, 471, 474, 477, 480, 486, 489, 492, 498, 502, 505, 509, 514, 519, 525, 530, 534, 539, 547, 555, 561, 570, 581, 593, 600, 609, 613, 620, 628, 632, 636, 643, 650, 658, 664, 673, 684, 699, 711, 727, 735, 744, 749, 754, 758, 766, 771, 775, 778, 782, 784, 789, 791, 796, 802, 808, 814, 820, 828, 835, 840, 844, 849, 853, 858, 866, 872, 879, 892, 901, 915, 930, 941, 949, 953, 964, 975, 978}
func (i Op) String() string {
if i >= Op(len(_Op_index)-1) {

View File

@ -1974,7 +1974,7 @@ func (w *exportWriter) expr(n ir.Node) {
w.expr(n.Y)
w.typ(n.Type())
case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR:
case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARR, ir.OSLICE2ARRPTR:
n := n.(*ir.ConvExpr)
w.op(n.Op())
w.pos(n.Pos())

View File

@ -1484,7 +1484,7 @@ func (r *importReader) node() ir.Node {
n.SetType(r.typ())
return n
case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR:
case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARR, ir.OSLICE2ARRPTR:
n := ir.NewConvExpr(r.pos(), op, r.typ(), r.expr())
n.SetImplicit(r.bool())
return n

View File

@ -579,11 +579,16 @@ func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
return ir.OCONVNOP, ""
}
// 11. src is a slice and dst is a pointer-to-array.
// 11. src is a slice and dst is an array or pointer-to-array.
// They must have same element type.
if src.IsSlice() && dst.IsPtr() && dst.Elem().IsArray() &&
types.Identical(src.Elem(), dst.Elem().Elem()) {
return ir.OSLICE2ARRPTR, ""
if src.IsSlice() {
if dst.IsArray() && types.Identical(src.Elem(), dst.Elem()) {
return ir.OSLICE2ARR, ""
}
if dst.IsPtr() && dst.Elem().IsArray() &&
types.Identical(src.Elem(), dst.Elem().Elem()) {
return ir.OSLICE2ARRPTR, ""
}
}
return ir.OXXX, ""

View File

@ -503,3 +503,21 @@ func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
return cheap
}
// walkSliceToArray walks an OSLICE2ARR expression.
func walkSliceToArray(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
// Replace T(x) with *(*T)(x).
conv := typecheck.Expr(ir.NewConvExpr(base.Pos, ir.OCONV, types.NewPtr(n.Type()), n.X)).(*ir.ConvExpr)
deref := typecheck.Expr(ir.NewStarExpr(base.Pos, conv)).(*ir.StarExpr)
// The OSLICE2ARRPTR conversion handles checking the slice length,
// so the dereference can't fail.
//
// However, this is more than just an optimization: if T is a
// zero-length array, then x (and thus (*T)(x)) can be nil, but T(x)
// should *not* panic. So suppressing the nil check here is
// necessary for correctness in that case.
deref.SetBounded(true)
return walkExpr(deref, init)
}

View File

@ -227,6 +227,10 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node {
n := n.(*ir.ConvExpr)
return walkConv(n, init)
case ir.OSLICE2ARR:
n := n.(*ir.ConvExpr)
return walkSliceToArray(n, init)
case ir.OSLICE2ARRPTR:
n := n.(*ir.ConvExpr)
n.X = walkExpr(n.X, init)

View File

@ -312,7 +312,8 @@ func mayCall(n ir.Node) bool {
return true
case ir.OINDEX, ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR,
ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODYNAMICDOTTYPE, ir.ODIV, ir.OMOD, ir.OSLICE2ARRPTR:
ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODYNAMICDOTTYPE, ir.ODIV, ir.OMOD,
ir.OSLICE2ARR, ir.OSLICE2ARRPTR:
// These ops might panic, make sure they are done
// before we start marshaling args for a call. See issue 16760.
return true

View File

@ -151,7 +151,7 @@ var boundsErrorFmts = [...]string{
boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
boundsSlice3B: "slice bounds out of range [:%x:%y]",
boundsSlice3C: "slice bounds out of range [%x:%y:]",
boundsConvert: "cannot convert slice with length %y to pointer to array with length %x",
boundsConvert: "cannot convert slice with length %y to array or pointer to array with length %x",
}
// boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y.

View File

@ -197,9 +197,9 @@ func goPanicSlice3CU(x uint, y int) {
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C})
}
// failures in the conversion (*[x]T)s, 0 <= x <= y, x == cap(s)
// failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s)
func goPanicSliceConvert(x int, y int) {
panicCheck1(getcallerpc(), "slice length too short to convert to pointer to array")
panicCheck1(getcallerpc(), "slice length too short to convert to array or pointer to array")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsConvert})
}

View File

@ -23,25 +23,47 @@ func wantPanic(fn func(), s string) {
func main() {
s := make([]byte, 8, 10)
for i := range s {
s[i] = byte(i)
}
if p := (*[8]byte)(s); &p[0] != &s[0] {
panic("*[8]byte conversion failed")
}
if [8]byte(s) != *(*[8]byte)(s) {
panic("[8]byte conversion failed")
}
wantPanic(
func() {
_ = (*[9]byte)(s)
},
"runtime error: cannot convert slice with length 8 to pointer to array with length 9",
"runtime error: cannot convert slice with length 8 to array or pointer to array with length 9",
)
wantPanic(
func() {
_ = [9]byte(s)
},
"runtime error: cannot convert slice with length 8 to array or pointer to array with length 9",
)
var n []byte
if p := (*[0]byte)(n); p != nil {
panic("nil slice converted to *[0]byte should be nil")
}
_ = [0]byte(n)
z := make([]byte, 0)
if p := (*[0]byte)(z); p == nil {
panic("empty slice converted to *[0]byte should be non-nil")
}
_ = [0]byte(z)
var p *[]byte
wantPanic(
func() {
_ = [0]byte(*p) // evaluating *p should still panic
},
"runtime error: invalid memory address or nil pointer dereference",
)
// Test with named types
type Slice []int

View File

@ -105,6 +105,10 @@ func slice12(x []int) *[1]int { // ERROR "leaking param: x to result ~r0 level=0
return (*[1]int)(x)
}
func slice13(x []*int) [1]*int { // ERROR "leaking param: x to result ~r0 level=1$"
return [1]*int(x)
}
func envForDir(dir string) []string { // ERROR "dir does not escape"
env := os.Environ()
return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape"