aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2022-09-12 13:01:57 -0700
committerMatthew Dempsky <mdempsky@google.com>2022-09-19 18:58:26 +0000
commitceffdc8545c3155b030de9e91d399dc34bd3c678 (patch)
treefb5079fbaef6a3178c80927ea89df3a2a7bc1c4b /src
parent29153be75763b7cbf9395d732f454336e3df0286 (diff)
downloadgo-ceffdc8545c3155b030de9e91d399dc34bd3c678.tar.xz
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>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/escape/expr.go4
-rw-r--r--src/cmd/compile/internal/ir/expr.go2
-rw-r--r--src/cmd/compile/internal/ir/fmt.go2
-rw-r--r--src/cmd/compile/internal/ir/node.go1
-rw-r--r--src/cmd/compile/internal/ir/op_string.go273
-rw-r--r--src/cmd/compile/internal/typecheck/iexport.go2
-rw-r--r--src/cmd/compile/internal/typecheck/iimport.go2
-rw-r--r--src/cmd/compile/internal/typecheck/subr.go13
-rw-r--r--src/cmd/compile/internal/walk/convert.go18
-rw-r--r--src/cmd/compile/internal/walk/expr.go4
-rw-r--r--src/cmd/compile/internal/walk/walk.go3
-rw-r--r--src/runtime/error.go2
-rw-r--r--src/runtime/panic.go4
13 files changed, 183 insertions, 147 deletions
diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go
index fd758bbf20..fc56530969 100644
--- a/src/cmd/compile/internal/escape/expr.go
+++ b/src/cmd/compile/internal/escape/expr.go
@@ -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)
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
index ff315bd027..a481b14f8b 100644
--- a/src/cmd/compile/internal/ir/expr.go
+++ b/src/cmd/compile/internal/ir/expr.go
@@ -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
}
}
diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go
index d051c88a29..7a0d8a62c1 100644
--- a/src/cmd/compile/internal/ir/fmt.go
+++ b/src/cmd/compile/internal/ir/fmt.go
@@ -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 {
diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go
index 7a4fb02f25..bda3957af9 100644
--- a/src/cmd/compile/internal/ir/node.go
+++ b/src/cmd/compile/internal/ir/node.go
@@ -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.
diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go
index e44168c7ba..d84a08e2a1 100644
--- a/src/cmd/compile/internal/ir/op_string.go
+++ b/src/cmd/compile/internal/ir/op_string.go
@@ -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) {
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go
index 848408d240..3e65425398 100644
--- a/src/cmd/compile/internal/typecheck/iexport.go
+++ b/src/cmd/compile/internal/typecheck/iexport.go
@@ -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())
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index 80ae0259e8..533ee99c21 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -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
diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go
index eab71556d3..f616b13781 100644
--- a/src/cmd/compile/internal/typecheck/subr.go
+++ b/src/cmd/compile/internal/typecheck/subr.go
@@ -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, ""
diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go
index 57f28e9800..c67a29fc09 100644
--- a/src/cmd/compile/internal/walk/convert.go
+++ b/src/cmd/compile/internal/walk/convert.go
@@ -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)
+}
diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go
index 2842c53df2..c12fb20106 100644
--- a/src/cmd/compile/internal/walk/expr.go
+++ b/src/cmd/compile/internal/walk/expr.go
@@ -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)
diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go
index d6b09866f7..f5a2f9b9ac 100644
--- a/src/cmd/compile/internal/walk/walk.go
+++ b/src/cmd/compile/internal/walk/walk.go
@@ -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
diff --git a/src/runtime/error.go b/src/runtime/error.go
index b11473c634..a211fbf515 100644
--- a/src/runtime/error.go
+++ b/src/runtime/error.go
@@ -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.
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index 92ef96882f..26618db7ce 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -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})
}