From 3d5c715bf299fb662104d70d612f3f0303e542d9 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sat, 30 Jan 2021 21:15:40 -0800 Subject: [PATCH] [dev.typeparams] Handling multiple type arguments for call via new node OLIST Will now run "go tool compile -G=2 -W=2" on a simple generic function with multiple type parameters and a call to that function with multiple explicit type arguments. We will likely move to have a separate function/type instantiation node, in order distinguish these cases from normal index expressions. Change-Id: I0a571902d63785cc06240ed4ba0495923403b511 Reviewed-on: https://go-review.googlesource.com/c/go/+/288433 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/ir/expr.go | 14 ++ src/cmd/compile/internal/ir/node.go | 1 + src/cmd/compile/internal/ir/node_gen.go | 26 ++++ src/cmd/compile/internal/ir/op_string.go | 177 +++++++++++----------- src/cmd/compile/internal/noder/expr.go | 17 ++- src/cmd/compile/internal/noder/helpers.go | 9 +- 6 files changed, 149 insertions(+), 95 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 92f93e98b85..7c60334c049 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -307,6 +307,20 @@ func (n *IndexExpr) SetOp(op Op) { } } +// A ListExpr is list of expressions +type ListExpr struct { + miniExpr + List Nodes +} + +func NewListExpr(pos src.XPos, list []Node) *ListExpr { + n := &ListExpr{} + n.pos = pos + n.op = OLIST + n.List = list + return n +} + // A KeyExpr is a Key: Value composite literal key. type KeyExpr struct { miniExpr diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index ffa7daf6b2b..590c428ac5f 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -190,6 +190,7 @@ const ( OGT // Left > Right ODEREF // *Left OINDEX // Left[Right] (index of array or slice) + OLIST // list of expressions OINDEXMAP // Left[Right] (index of map) OKEY // Left:Right (key:value in struct/array/map literal) OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking) diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index fe436867b2c..6f5eceb86de 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -249,6 +249,7 @@ func (n *CallExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } func (n *CallExpr) copy() Node { c := *n c.init = copyNodes(c.init) + c.Targs = copyNodes(c.Targs) c.Args = copyNodes(c.Args) c.KeepAlive = copyNames(c.KeepAlive) return &c @@ -260,6 +261,9 @@ func (n *CallExpr) doChildren(do func(Node) bool) bool { if n.X != nil && do(n.X) { return true } + if doNodes(n.Targs, do) { + return true + } if doNodes(n.Args, do) { return true } @@ -273,6 +277,7 @@ func (n *CallExpr) editChildren(edit func(Node) Node) { if n.X != nil { n.X = edit(n.X).(Node) } + editNodes(n.Targs, edit) editNodes(n.Args, edit) editNames(n.KeepAlive, edit) } @@ -745,6 +750,27 @@ func (n *LinksymOffsetExpr) editChildren(edit func(Node) Node) { editNodes(n.init, edit) } +func (n *ListExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } +func (n *ListExpr) copy() Node { + c := *n + c.init = copyNodes(c.init) + c.List = copyNodes(c.List) + return &c +} +func (n *ListExpr) doChildren(do func(Node) bool) bool { + if doNodes(n.init, do) { + return true + } + if doNodes(n.List, do) { + return true + } + return false +} +func (n *ListExpr) editChildren(edit func(Node) Node) { + editNodes(n.init, edit) + editNodes(n.List, edit) +} + func (n *LogicalExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } func (n *LogicalExpr) copy() Node { c := *n diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 15c60baf449..390b0eecfea 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -74,97 +74,98 @@ func _() { _ = 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[ORECOVER-99] - _ = x[ORECV-100] - _ = x[ORUNESTR-101] - _ = x[OSELRECV2-102] - _ = x[OIOTA-103] - _ = x[OREAL-104] - _ = x[OIMAG-105] - _ = x[OCOMPLEX-106] - _ = x[OALIGNOF-107] - _ = x[OOFFSETOF-108] - _ = x[OSIZEOF-109] - _ = x[OMETHEXPR-110] - _ = x[OSTMTEXPR-111] - _ = x[OBLOCK-112] - _ = x[OBREAK-113] - _ = x[OCASE-114] - _ = x[OCONTINUE-115] - _ = x[ODEFER-116] - _ = x[OFALL-117] - _ = x[OFOR-118] - _ = x[OFORUNTIL-119] - _ = x[OGOTO-120] - _ = x[OIF-121] - _ = x[OLABEL-122] - _ = x[OGO-123] - _ = x[ORANGE-124] - _ = x[ORETURN-125] - _ = x[OSELECT-126] - _ = x[OSWITCH-127] - _ = x[OTYPESW-128] - _ = x[OTCHAN-129] - _ = x[OTMAP-130] - _ = x[OTSTRUCT-131] - _ = x[OTINTER-132] - _ = x[OTFUNC-133] - _ = x[OTARRAY-134] - _ = x[OTSLICE-135] - _ = x[OINLCALL-136] - _ = x[OEFACE-137] - _ = x[OITAB-138] - _ = x[OIDATA-139] - _ = x[OSPTR-140] - _ = x[OCFUNC-141] - _ = x[OCHECKNIL-142] - _ = x[OVARDEF-143] - _ = x[OVARKILL-144] - _ = x[OVARLIVE-145] - _ = x[ORESULT-146] - _ = x[OINLMARK-147] - _ = x[OLINKSYMOFFSET-148] - _ = x[OTAILCALL-149] - _ = x[OGETG-150] - _ = x[OEND-151] + _ = x[OLIST-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[ORECOVER-100] + _ = x[ORECV-101] + _ = x[ORUNESTR-102] + _ = x[OSELRECV2-103] + _ = x[OIOTA-104] + _ = x[OREAL-105] + _ = x[OIMAG-106] + _ = x[OCOMPLEX-107] + _ = x[OALIGNOF-108] + _ = x[OOFFSETOF-109] + _ = x[OSIZEOF-110] + _ = x[OMETHEXPR-111] + _ = x[OSTMTEXPR-112] + _ = x[OBLOCK-113] + _ = x[OBREAK-114] + _ = x[OCASE-115] + _ = x[OCONTINUE-116] + _ = x[ODEFER-117] + _ = x[OFALL-118] + _ = x[OFOR-119] + _ = x[OFORUNTIL-120] + _ = x[OGOTO-121] + _ = x[OIF-122] + _ = x[OLABEL-123] + _ = x[OGO-124] + _ = x[ORANGE-125] + _ = x[ORETURN-126] + _ = x[OSELECT-127] + _ = x[OSWITCH-128] + _ = x[OTYPESW-129] + _ = x[OTCHAN-130] + _ = x[OTMAP-131] + _ = x[OTSTRUCT-132] + _ = x[OTINTER-133] + _ = x[OTFUNC-134] + _ = x[OTARRAY-135] + _ = x[OTSLICE-136] + _ = x[OINLCALL-137] + _ = x[OEFACE-138] + _ = x[OITAB-139] + _ = x[OIDATA-140] + _ = x[OSPTR-141] + _ = x[OCFUNC-142] + _ = x[OCHECKNIL-143] + _ = x[OVARDEF-144] + _ = x[OVARKILL-145] + _ = x[OVARLIVE-146] + _ = x[ORESULT-147] + _ = x[OINLMARK-148] + _ = x[OLINKSYMOFFSET-149] + _ = x[OTAILCALL-150] + _ = x[OGETG-151] + _ = x[OEND-152] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRSTMTEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXLISTINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRSTMTEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 388, 391, 400, 403, 407, 415, 422, 431, 444, 447, 450, 453, 456, 459, 462, 468, 471, 474, 480, 484, 487, 491, 496, 501, 507, 512, 516, 521, 529, 537, 543, 552, 563, 570, 574, 581, 589, 593, 597, 601, 608, 615, 623, 629, 637, 645, 650, 655, 659, 667, 672, 676, 679, 687, 691, 693, 698, 700, 705, 711, 717, 723, 729, 734, 738, 745, 751, 756, 762, 768, 775, 780, 784, 789, 793, 798, 806, 812, 819, 826, 832, 839, 852, 860, 864, 867} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 384, 392, 395, 404, 407, 411, 419, 426, 435, 448, 451, 454, 457, 460, 463, 466, 472, 475, 478, 484, 488, 491, 495, 500, 505, 511, 516, 520, 525, 533, 541, 547, 556, 567, 574, 578, 585, 593, 597, 601, 605, 612, 619, 627, 633, 641, 649, 654, 659, 663, 671, 676, 680, 683, 691, 695, 697, 702, 704, 709, 715, 721, 727, 733, 738, 742, 749, 755, 760, 766, 772, 779, 784, 788, 793, 797, 802, 810, 816, 823, 830, 836, 843, 856, 864, 868, 871} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 79b94638e88..41d54441d4c 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -99,10 +99,23 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } return Call(pos, g.typ(typ), g.expr(expr.Fun), g.exprs(expr.ArgList), expr.HasDots) case *syntax.IndexExpr: + var index ir.Node + + // We are using IndexExpr in two ways, as an standard index + // operation (with expression) and as a function/type + // instantiation (with a type list). We will soon make this + // clearer by having separate function/type instantiation nodes. if _, ok := expr.Index.(*syntax.ListExpr); ok { - panic("more than one type argument") + // List of types for a generic function call or type instantiation + index = ir.NewListExpr(pos, g.exprList(expr.Index)) + } else { + index = g.expr(expr.Index) + if index.Op() == ir.OTYPE { + // Single type for a generic function call or type instantiation + index = ir.NewListExpr(pos, []ir.Node{index}) + } } - return Index(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index)) + return Index(pos, g.typ(typ), g.expr(expr.X), index) case *syntax.ParenExpr: return g.expr(expr.X) // skip parens; unneeded after parse+typecheck case *syntax.SelectorExpr: diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 2a6f30e026e..d97dacfc8b5 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -118,12 +118,11 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) var targs []ir.Node if indexExpr, ok := fun.(*ir.IndexExpr); ok { - if indexExpr.Index.Op() == ir.OTYPE { + if indexExpr.Index.Op() == ir.OLIST { // Called function is an instantiated generic function - // TODO this handles just one type argument for now fun = indexExpr.X - targs = make([]ir.Node, 1, 1) - targs[0] = indexExpr.Index + // Don't need to copy, since the node list was just created + targs = indexExpr.Index.(*ir.ListExpr).List } } @@ -235,7 +234,7 @@ func method(typ *types.Type, index int) *types.Field { } func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node { - if index.Op() == ir.OTYPE { + if index.Op() == ir.OLIST { n := ir.NewIndexExpr(pos, x, index) typed(typ, n) return n