[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 <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Dan Scales 2021-01-30 21:15:40 -08:00
parent 13a7412983
commit 3d5c715bf2
6 changed files with 149 additions and 95 deletions

View file

@ -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. // A KeyExpr is a Key: Value composite literal key.
type KeyExpr struct { type KeyExpr struct {
miniExpr miniExpr

View file

@ -190,6 +190,7 @@ const (
OGT // Left > Right OGT // Left > Right
ODEREF // *Left ODEREF // *Left
OINDEX // Left[Right] (index of array or slice) OINDEX // Left[Right] (index of array or slice)
OLIST // list of expressions
OINDEXMAP // Left[Right] (index of map) OINDEXMAP // Left[Right] (index of map)
OKEY // Left:Right (key:value in struct/array/map literal) OKEY // Left:Right (key:value in struct/array/map literal)
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking) OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)

View file

@ -249,6 +249,7 @@ func (n *CallExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
func (n *CallExpr) copy() Node { func (n *CallExpr) copy() Node {
c := *n c := *n
c.init = copyNodes(c.init) c.init = copyNodes(c.init)
c.Targs = copyNodes(c.Targs)
c.Args = copyNodes(c.Args) c.Args = copyNodes(c.Args)
c.KeepAlive = copyNames(c.KeepAlive) c.KeepAlive = copyNames(c.KeepAlive)
return &c return &c
@ -260,6 +261,9 @@ func (n *CallExpr) doChildren(do func(Node) bool) bool {
if n.X != nil && do(n.X) { if n.X != nil && do(n.X) {
return true return true
} }
if doNodes(n.Targs, do) {
return true
}
if doNodes(n.Args, do) { if doNodes(n.Args, do) {
return true return true
} }
@ -273,6 +277,7 @@ func (n *CallExpr) editChildren(edit func(Node) Node) {
if n.X != nil { if n.X != nil {
n.X = edit(n.X).(Node) n.X = edit(n.X).(Node)
} }
editNodes(n.Targs, edit)
editNodes(n.Args, edit) editNodes(n.Args, edit)
editNames(n.KeepAlive, edit) editNames(n.KeepAlive, edit)
} }
@ -745,6 +750,27 @@ func (n *LinksymOffsetExpr) editChildren(edit func(Node) Node) {
editNodes(n.init, edit) 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) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
func (n *LogicalExpr) copy() Node { func (n *LogicalExpr) copy() Node {
c := *n c := *n

View file

@ -74,97 +74,98 @@ func _() {
_ = x[OGT-63] _ = x[OGT-63]
_ = x[ODEREF-64] _ = x[ODEREF-64]
_ = x[OINDEX-65] _ = x[OINDEX-65]
_ = x[OINDEXMAP-66] _ = x[OLIST-66]
_ = x[OKEY-67] _ = x[OINDEXMAP-67]
_ = x[OSTRUCTKEY-68] _ = x[OKEY-68]
_ = x[OLEN-69] _ = x[OSTRUCTKEY-69]
_ = x[OMAKE-70] _ = x[OLEN-70]
_ = x[OMAKECHAN-71] _ = x[OMAKE-71]
_ = x[OMAKEMAP-72] _ = x[OMAKECHAN-72]
_ = x[OMAKESLICE-73] _ = x[OMAKEMAP-73]
_ = x[OMAKESLICECOPY-74] _ = x[OMAKESLICE-74]
_ = x[OMUL-75] _ = x[OMAKESLICECOPY-75]
_ = x[ODIV-76] _ = x[OMUL-76]
_ = x[OMOD-77] _ = x[ODIV-77]
_ = x[OLSH-78] _ = x[OMOD-78]
_ = x[ORSH-79] _ = x[OLSH-79]
_ = x[OAND-80] _ = x[ORSH-80]
_ = x[OANDNOT-81] _ = x[OAND-81]
_ = x[ONEW-82] _ = x[OANDNOT-82]
_ = x[ONOT-83] _ = x[ONEW-83]
_ = x[OBITNOT-84] _ = x[ONOT-84]
_ = x[OPLUS-85] _ = x[OBITNOT-85]
_ = x[ONEG-86] _ = x[OPLUS-86]
_ = x[OOROR-87] _ = x[ONEG-87]
_ = x[OPANIC-88] _ = x[OOROR-88]
_ = x[OPRINT-89] _ = x[OPANIC-89]
_ = x[OPRINTN-90] _ = x[OPRINT-90]
_ = x[OPAREN-91] _ = x[OPRINTN-91]
_ = x[OSEND-92] _ = x[OPAREN-92]
_ = x[OSLICE-93] _ = x[OSEND-93]
_ = x[OSLICEARR-94] _ = x[OSLICE-94]
_ = x[OSLICESTR-95] _ = x[OSLICEARR-95]
_ = x[OSLICE3-96] _ = x[OSLICESTR-96]
_ = x[OSLICE3ARR-97] _ = x[OSLICE3-97]
_ = x[OSLICEHEADER-98] _ = x[OSLICE3ARR-98]
_ = x[ORECOVER-99] _ = x[OSLICEHEADER-99]
_ = x[ORECV-100] _ = x[ORECOVER-100]
_ = x[ORUNESTR-101] _ = x[ORECV-101]
_ = x[OSELRECV2-102] _ = x[ORUNESTR-102]
_ = x[OIOTA-103] _ = x[OSELRECV2-103]
_ = x[OREAL-104] _ = x[OIOTA-104]
_ = x[OIMAG-105] _ = x[OREAL-105]
_ = x[OCOMPLEX-106] _ = x[OIMAG-106]
_ = x[OALIGNOF-107] _ = x[OCOMPLEX-107]
_ = x[OOFFSETOF-108] _ = x[OALIGNOF-108]
_ = x[OSIZEOF-109] _ = x[OOFFSETOF-109]
_ = x[OMETHEXPR-110] _ = x[OSIZEOF-110]
_ = x[OSTMTEXPR-111] _ = x[OMETHEXPR-111]
_ = x[OBLOCK-112] _ = x[OSTMTEXPR-112]
_ = x[OBREAK-113] _ = x[OBLOCK-113]
_ = x[OCASE-114] _ = x[OBREAK-114]
_ = x[OCONTINUE-115] _ = x[OCASE-115]
_ = x[ODEFER-116] _ = x[OCONTINUE-116]
_ = x[OFALL-117] _ = x[ODEFER-117]
_ = x[OFOR-118] _ = x[OFALL-118]
_ = x[OFORUNTIL-119] _ = x[OFOR-119]
_ = x[OGOTO-120] _ = x[OFORUNTIL-120]
_ = x[OIF-121] _ = x[OGOTO-121]
_ = x[OLABEL-122] _ = x[OIF-122]
_ = x[OGO-123] _ = x[OLABEL-123]
_ = x[ORANGE-124] _ = x[OGO-124]
_ = x[ORETURN-125] _ = x[ORANGE-125]
_ = x[OSELECT-126] _ = x[ORETURN-126]
_ = x[OSWITCH-127] _ = x[OSELECT-127]
_ = x[OTYPESW-128] _ = x[OSWITCH-128]
_ = x[OTCHAN-129] _ = x[OTYPESW-129]
_ = x[OTMAP-130] _ = x[OTCHAN-130]
_ = x[OTSTRUCT-131] _ = x[OTMAP-131]
_ = x[OTINTER-132] _ = x[OTSTRUCT-132]
_ = x[OTFUNC-133] _ = x[OTINTER-133]
_ = x[OTARRAY-134] _ = x[OTFUNC-134]
_ = x[OTSLICE-135] _ = x[OTARRAY-135]
_ = x[OINLCALL-136] _ = x[OTSLICE-136]
_ = x[OEFACE-137] _ = x[OINLCALL-137]
_ = x[OITAB-138] _ = x[OEFACE-138]
_ = x[OIDATA-139] _ = x[OITAB-139]
_ = x[OSPTR-140] _ = x[OIDATA-140]
_ = x[OCFUNC-141] _ = x[OSPTR-141]
_ = x[OCHECKNIL-142] _ = x[OCFUNC-142]
_ = x[OVARDEF-143] _ = x[OCHECKNIL-143]
_ = x[OVARKILL-144] _ = x[OVARDEF-144]
_ = x[OVARLIVE-145] _ = x[OVARKILL-145]
_ = x[ORESULT-146] _ = x[OVARLIVE-146]
_ = x[OINLMARK-147] _ = x[ORESULT-147]
_ = x[OLINKSYMOFFSET-148] _ = x[OINLMARK-148]
_ = x[OTAILCALL-149] _ = x[OLINKSYMOFFSET-149]
_ = x[OGETG-150] _ = x[OTAILCALL-150]
_ = x[OEND-151] _ = 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 { func (i Op) String() string {
if i >= Op(len(_Op_index)-1) { if i >= Op(len(_Op_index)-1) {

View file

@ -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) return Call(pos, g.typ(typ), g.expr(expr.Fun), g.exprs(expr.ArgList), expr.HasDots)
case *syntax.IndexExpr: 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 { 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: case *syntax.ParenExpr:
return g.expr(expr.X) // skip parens; unneeded after parse+typecheck return g.expr(expr.X) // skip parens; unneeded after parse+typecheck
case *syntax.SelectorExpr: case *syntax.SelectorExpr:

View file

@ -118,12 +118,11 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
var targs []ir.Node var targs []ir.Node
if indexExpr, ok := fun.(*ir.IndexExpr); ok { 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 // Called function is an instantiated generic function
// TODO this handles just one type argument for now
fun = indexExpr.X fun = indexExpr.X
targs = make([]ir.Node, 1, 1) // Don't need to copy, since the node list was just created
targs[0] = indexExpr.Index 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 { 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) n := ir.NewIndexExpr(pos, x, index)
typed(typ, n) typed(typ, n)
return n return n