aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/expr.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-01-22 13:29:59 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-01-23 01:20:17 +0000
commit2b95c28b18872b2d61ac9e9b32f63c76b619e86b (patch)
tree98bb6f864794ce52b6af0992c018c1a172ee98b1 /src/cmd/compile/internal/noder/expr.go
parent1946a77e69b0f8620ab58472c08e061bd8a5ba4b (diff)
downloadgo-2b95c28b18872b2d61ac9e9b32f63c76b619e86b.tar.xz
[dev.typeparams] cmd/compile: refactor SelectorExpr code into helpers
This CL refactors the SelectorExpr-handling code added in CL 285373 into helper functions that can eventually be reused by iimport. Change-Id: I15b4a96c242f63cb370d7492ed08168550724f47 Reviewed-on: https://go-review.googlesource.com/c/go/+/285953 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/noder/expr.go')
-rw-r--r--src/cmd/compile/internal/noder/expr.go117
1 files changed, 42 insertions, 75 deletions
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go
index b38e9cfb4e..5a2cae12e3 100644
--- a/src/cmd/compile/internal/noder/expr.go
+++ b/src/cmd/compile/internal/noder/expr.go
@@ -107,7 +107,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
}
}
- return g.selectorExpr(pos, typ, expr)
+ return g.selectorExpr(pos, expr)
case *syntax.SliceExpr:
return Slice(pos, g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2]))
@@ -131,88 +131,55 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
// selectorExpr resolves the choice of ODOT, ODOTPTR, OCALLPART (eventually
// ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
// than in typecheck.go.
-func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node {
- x := g.expr(expr.X)
+func (g *irgen) selectorExpr(pos src.XPos, expr *syntax.SelectorExpr) ir.Node {
selinfo := g.info.Selections[expr]
- nindex := len(selinfo.Index())
- // Iterate through the selections from types2. If nindex > 1, then we will
- // create extra nodes to deal with embedded fields.
- for i := 0; i < nindex; i++ {
- var f *types.Field
- var n *ir.SelectorExpr
+ // Everything up to the last selection is an implicit embedded field access,
+ // and the last selection is determined by selinfo.Kind().
+ index := selinfo.Index()
+ embeds, last := index[:len(index)-1], index[len(index)-1]
- op := ir.ODOT
- index := selinfo.Index()[i]
- xt := x.Type()
- origxt := xt
- if xt.IsPtr() && !xt.Elem().IsInterface() {
- // Get to the base type, but remember that we skipped the ptr
- xt = xt.Elem()
- op = ir.ODOTPTR
- }
- types.CalcSize(xt)
- // Everything up to the last selection is an embedded field
- // access, and the last selection is determined by selinfo.Kind().
- if i < nindex-1 || selinfo.Kind() == types2.FieldVal {
- f = xt.Field(index)
- sym := f.Sym
- n = ir.NewSelectorExpr(pos, op, x, sym)
- if i < nindex-1 {
- n.SetImplicit(true)
- typed(f.Type, n)
- }
- } else if selinfo.Kind() == types2.MethodExpr {
- var ms *types.Fields
- if xt.IsInterface() {
- // TODO(danscales,mdempsky): interface method sets
- // are not sorted the same between types and
- // types2. In particular, this will likely fail if
- // an interface contains unexported methods from
- // two different packages (due to cross-package
- // interface embedding).
- ms = xt.Fields()
- } else {
- mt := types.ReceiverBaseType(xt)
- ms = mt.Methods()
- }
- f = ms.Slice()[index]
- n = ir.NewSelectorExpr(pos, ir.OMETHEXPR, x, f.Sym)
- } else { // types.MethodVal
- if xt.IsInterface() {
- f = xt.Field(index)
+ x := g.expr(expr.X)
+ for _, ix := range embeds {
+ x = Implicit(DotField(pos, x, ix))
+ }
+
+ kind := selinfo.Kind()
+ if kind == types2.FieldVal {
+ return DotField(pos, x, last)
+ }
+
+ // TODO(danscales,mdempsky): Interface method sets are not sorted the
+ // same between types and types2. In particular, using "last" here
+ // without conversion will likely fail if an interface contains
+ // unexported methods from two different packages (due to cross-package
+ // interface embedding).
+
+ method := selinfo.Obj().(*types2.Func)
+
+ // Add implicit addr/deref for method values, if needed.
+ if kind == types2.MethodVal && !x.Type().IsInterface() {
+ recvTyp := method.Type().(*types2.Signature).Recv().Type()
+ _, wantPtr := recvTyp.(*types2.Pointer)
+ havePtr := x.Type().IsPtr()
+
+ if havePtr != wantPtr {
+ if havePtr {
+ x = Implicit(Deref(pos, x))
} else {
- f = xt.Methods().Slice()[index]
- rcvr := f.Type.Recv().Type
- if rcvr.IsPtr() && types.Identical(rcvr.Elem(), origxt) {
- addr := typecheck.NodAddrAt(pos, x)
- addr.SetImplicit(true)
- typed(xt.PtrTo(), addr)
- x = addr
- } else if op == ir.ODOTPTR && !rcvr.IsPtr() {
- star := ir.NewStarExpr(pos, x)
- star.SetImplicit(true)
- typed(xt, star)
- x = star
- }
+ x = Implicit(Addr(pos, x))
}
- // We will change OCALLPART to ODOTMETH or ODOTINTER in
- // Call() if n is actually called.
- n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, f.Sym)
}
- n.Selection = f
- x = n
+ if !g.match(x.Type(), recvTyp, false) {
+ base.FatalfAt(pos, "expected %L to have type %v", x, recvTyp)
+ }
}
- // We don't set type on x for the last index (i == nindex - 1), since that
- // is the actual selection (ignoring embedded fields) and may be an
- // OMETHEXPR or OCALLPART operation. In those cases, the type to set on the
- // node will be different from the type derived from the field/method
- // selection. Instead for the last index, we always set the type (at the
- // end of the function) from g.typ(typ).
- typed(g.typ(typ), x)
- types.CalcSize(x.Type())
- return x
+ n := DotMethod(pos, x, last)
+ if have, want := n.Sym(), g.selector(method); have != want {
+ base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
+ }
+ return n
}
func (g *irgen) exprList(expr syntax.Expr) []ir.Node {