aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-07-06 10:53:00 -0700
committerDan Scales <danscales@google.com>2021-07-07 17:31:57 +0000
commitb4844c9f54eb6a559d8dc9333cf5b1e66dab8167 (patch)
treec14c3561c5ccc3542d9b53b3761229b271aa887b /src/cmd
parent4676c3675e85a8a82a1513ef1f5e38aebc80ddc8 (diff)
downloadgo-b4844c9f54eb6a559d8dc9333cf5b1e66dab8167.tar.gz
go-b4844c9f54eb6a559d8dc9333cf5b1e66dab8167.zip
[dev.typeparams] cmd/compile: handle the (*T).M method expression with dictionaries
The (*T).M method expression is where M is a value method, but the type (*T) is a pointer to the main type. In this case, after following any embedded fields, we need to add an extra star operator when using the receiver arg in the closure call. Thanks to Cuong for finding/pointing out an example for this case (typeparam/mdempsky/14.go) This example also shows that we now need the ability to export/import OEFACE and OIDATA, which I added. Change-Id: Ida0f81ce757fff78fec6276c60052ed71d207454 Reviewed-on: https://go-review.googlesource.com/c/go/+/333014 Run-TryBot: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Trust: Dan Scales <danscales@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/noder/stencil.go30
-rw-r--r--src/cmd/compile/internal/typecheck/iexport.go4
-rw-r--r--src/cmd/compile/internal/typecheck/iimport.go4
3 files changed, 22 insertions, 16 deletions
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index dbaebf7623..656cab84d1 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -94,7 +94,7 @@ func (g *irgen) stencil() {
// generic F, not immediately called
closureRequired = true
}
- if n.Op() == ir.OMETHEXPR && len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) {
+ if n.Op() == ir.OMETHEXPR && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) {
// T.M, T a type which is generic, not immediately
// called. Not necessary if the method selected is
// actually for an embedded interface field.
@@ -229,6 +229,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
outerInfo = g.instInfoMap[outer.Sym()]
}
usingSubdict := false
+ valueMethod := false
if x.Op() == ir.OFUNCINST {
inst := x.(*ir.InstExpr)
@@ -269,16 +270,10 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
}
} else { // ir.OMETHEXPR
// Method expression T.M where T is a generic type.
- // TODO: Is (*T).M right?
se := x.(*ir.SelectorExpr)
- targs := se.X.Type().RParams()
+ targs := deref(se.X.Type()).RParams()
if len(targs) == 0 {
- if se.X.Type().IsPtr() {
- targs = se.X.Type().Elem().RParams()
- if len(targs) == 0 {
- panic("bad")
- }
- }
+ panic("bad")
}
// se.X.Type() is the top-level type of the method expression. To
@@ -295,6 +290,10 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
break
}
}
+ if !gf.Type().Recv().Type.IsPtr() {
+ // Remember if value method, so we can detect (*T).M case.
+ valueMethod = true
+ }
target = g.getInstantiation(gf, targs, true)
dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true)
if infoPrintMode {
@@ -446,8 +445,15 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
// If we are doing a method expression, we need to
// explicitly traverse any embedded fields in the receiver
// argument in order to call the method instantiation.
- dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, formalParams[0].Nname.(*ir.Name), x.(*ir.SelectorExpr).Sel))
- args = append(args, dot.X)
+ arg0 := formalParams[0].Nname.(ir.Node)
+ arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X
+ if valueMethod && arg0.Type().IsPtr() {
+ // For handling the (*T).M case: if we have a pointer
+ // receiver after following all the embedded fields,
+ // but it's a value method, add a star operator.
+ arg0 = ir.NewStarExpr(arg0.Pos(), arg0)
+ }
+ args = append(args, arg0)
} else {
args = append(args, formalParams[i].Nname.(*ir.Name))
}
@@ -1342,7 +1348,7 @@ func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir
return newfields
}
-// defer does a single defer of type t, if it is a pointer type.
+// deref does a single deref of type t, if it is a pointer type.
func deref(t *types.Type) *types.Type {
if t.IsPtr() {
return t.Elem()
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go
index 82bbda5228..b717c373f5 100644
--- a/src/cmd/compile/internal/typecheck/iexport.go
+++ b/src/cmd/compile/internal/typecheck/iexport.go
@@ -1957,7 +1957,7 @@ func (w *exportWriter) expr(n ir.Node) {
w.typ(n.Type())
// unary expressions
- case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV:
+ case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA:
n := n.(*ir.UnaryExpr)
w.op(n.Op())
w.pos(n.Pos())
@@ -1993,7 +1993,7 @@ func (w *exportWriter) expr(n ir.Node) {
// binary expressions
case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
- ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR:
+ ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE:
n := n.(*ir.BinaryExpr)
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 17e60effd6..f178869e28 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -1497,7 +1497,7 @@ func (r *importReader) node() ir.Node {
return ir.NewLinksymOffsetExpr(pos, Lookup(name).Linksym(), int64(off), typ)
// unary expressions
- case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV:
+ case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA:
n := ir.NewUnaryExpr(r.pos(), op, r.expr())
if go117ExportTypes {
n.SetType(r.typ())
@@ -1521,7 +1521,7 @@ func (r *importReader) node() ir.Node {
// binary expressions
case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
- ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR:
+ ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE:
n := ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
if go117ExportTypes {
n.SetType(r.typ())