diff options
author | Dan Scales <danscales@google.com> | 2021-01-24 09:59:20 -0800 |
---|---|---|
committer | Dan Scales <danscales@google.com> | 2021-01-26 17:05:06 +0000 |
commit | 08a598f8c1c123fda3b7ad30659fa05a8be1ccde (patch) | |
tree | bab7a41df3b1819b7c0bd19900607247d01ed0ff /src/cmd/compile/internal/noder/expr.go | |
parent | cecc1dfcba15a06a06a7f3ea79e809e95c166c25 (diff) | |
download | go-08a598f8c1c123fda3b7ad30659fa05a8be1ccde.tar.gz go-08a598f8c1c123fda3b7ad30659fa05a8be1ccde.zip |
[dev.typeparams] cmd/compile: fix MethodExpr handling with embedded fields
The recent refactoring of SelectorExpr code to helpers broke the
handling of MethodExprs when there is an embedded field involved (e.g.
test/method7.go, line 48). If there is an embedded field involved, the
node op seen in DotMethod() is an ODOT rather than an OTYPE. Also, the
receiver type of the result should be the original type, but the new
code was using the last type after following the embedding path.
Change-Id: I13f7ea6448b03d3e8f974103ee3a027219ca8388
Reviewed-on: https://go-review.googlesource.com/c/go/+/286176
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder/expr.go')
-rw-r--r-- | src/cmd/compile/internal/noder/expr.go | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 5a2cae12e3..9212c67213 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -140,6 +140,7 @@ func (g *irgen) selectorExpr(pos src.XPos, expr *syntax.SelectorExpr) ir.Node { embeds, last := index[:len(index)-1], index[len(index)-1] x := g.expr(expr.X) + origx := x for _, ix := range embeds { x = Implicit(DotField(pos, x, ix)) } @@ -155,27 +156,37 @@ func (g *irgen) selectorExpr(pos src.XPos, expr *syntax.SelectorExpr) ir.Node { // unexported methods from two different packages (due to cross-package // interface embedding). + var n ir.Node 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 { - x = Implicit(Addr(pos, x)) + if kind == types2.MethodExpr { + // OMETHEXPR is unusual in using directly the node and type of the + // original OTYPE node (origx) before passing through embedded + // fields, even though the method is selected from the type + // (x.Type()) reached after following the embedded fields. We will + // actually drop any ODOT nodes we created due to the embedded + // fields. + n = MethodExpr(pos, origx, x.Type(), last) + } else { + // Add implicit addr/deref for method values, if needed. + if !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 { + x = Implicit(Addr(pos, x)) + } + } + if !g.match(x.Type(), recvTyp, false) { + base.FatalfAt(pos, "expected %L to have type %v", x, recvTyp) } } - if !g.match(x.Type(), recvTyp, false) { - base.FatalfAt(pos, "expected %L to have type %v", x, recvTyp) - } + n = DotMethod(pos, x, last) } - - 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) } |