]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: implement slice-to-array conversions
authorMatthew Dempsky <mdempsky@google.com>
Mon, 12 Sep 2022 20:01:57 +0000 (13:01 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 19 Sep 2022 18:58:26 +0000 (18:58 +0000)
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>
15 files changed:
src/cmd/compile/internal/escape/expr.go
src/cmd/compile/internal/ir/expr.go
src/cmd/compile/internal/ir/fmt.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/op_string.go
src/cmd/compile/internal/typecheck/iexport.go
src/cmd/compile/internal/typecheck/iimport.go
src/cmd/compile/internal/typecheck/subr.go
src/cmd/compile/internal/walk/convert.go
src/cmd/compile/internal/walk/expr.go
src/cmd/compile/internal/walk/walk.go
src/runtime/error.go
src/runtime/panic.go
test/convert4.go
test/escape_slice.go

index fd758bbf2081837cb4ef86a6875244f864f38c24..fc56530969bf2c865e1590f3fa91f608c66b9650 100644 (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)
index ff315bd02752226b6556a28b8ce4c0ca36359902..a481b14f8b94c0751aa416fe04cdb6e1077f5f3d 100644 (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
        }
 }
index d051c88a29e95806cd9313b4ef7c9c6851734d6d..7a0d8a62c1b87346d507d38840f3b05399a96f38 100644 (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 {
index 7a4fb02f25d01a79bd400a91547edebaf7a7b2b5..bda3957af9561104c43abf962da30ba8363bc30b 100644 (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.
index e44168c7ba369751b33f37c126a5eb2febdb4fbf..d84a08e2a1c9eb113b0e822c1a5ef8654766afb1 100644 (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) {
index 848408d240fa6a362d2bd677a89d2891d843554b..3e654253981364c987ede6209ecc35f3cd61eb37 100644 (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())
index 80ae0259e861b9f6720616850afa468c708276ec..533ee99c21d495c81753a6ef44a14b37651cb401 100644 (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
index eab71556d3f776f82f630e700ae21900773a0f1e..f616b13781c4d8f8d9b63ddcdff6f1e0b2cd3bef 100644 (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, ""
index 57f28e980026bce3ad59768b384f4db71de7c708..c67a29fc099fa1c12abd26650bab7987702eb744 100644 (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)
+}
index 2842c53df256e8bd907d821b71e5729963c2d3fb..c12fb20106dc3cd0c1b56196182080410e34b83c 100644 (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)
index d6b09866f71e91b7b6e6742edd5c9ec0329de340..f5a2f9b9ac340cb908ee4f9e98068b1490706a3d 100644 (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
index b11473c6346247666db7bb4dfb4fdf289949f765..a211fbf515517bbef14b249b9ba773211b1e7f8a 100644 (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.
index 92ef96882fad8627bf1e03a21d4332a7cd041b65..26618db7ceb470473bacdfa2d8969f63b258779f 100644 (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})
 }
 
index 2bc9c96a527fa15a9625cec9df3eb444cadccbd5..3cc0aea7be94a85a2a3ee4c965e54906388b5d26 100644 (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
index 055b60be4173cfe5a2ef6ba55b147133e9e2a8eb..7f94a755b99efc5e02d6fbda84705aa1c793e7cf 100644 (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"