mirror of
https://github.com/golang/go
synced 2024-11-26 16:36:49 -07:00
cmd/compile/internal/typecheck: simplify NewMethodExpr
This CL changes NewMethodExpr to directly construct the OMETHEXPR node, instead of running through the generic OXDOT typechecking machinery. Change-Id: Ic2af0bab6ff1aef45e8463bccb1f69c50db68f65 Reviewed-on: https://go-review.googlesource.com/c/go/+/520919 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
a2ec545e0a
commit
3761e3fbfd
@ -447,7 +447,7 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node {
|
||||
}
|
||||
}
|
||||
|
||||
n.X = typecheck(n.X, ctxExpr|ctxType)
|
||||
n.X = Expr(n.X)
|
||||
n.X = DefaultLit(n.X, nil)
|
||||
|
||||
t := n.X.Type()
|
||||
@ -458,7 +458,7 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node {
|
||||
}
|
||||
|
||||
if n.X.Op() == ir.OTYPE {
|
||||
return typecheckMethodExpr(n)
|
||||
base.FatalfAt(n.Pos(), "use NewMethodExpr to construct OMETHEXPR")
|
||||
}
|
||||
|
||||
if t.IsPtr() && !t.Elem().IsInterface() {
|
||||
|
@ -846,58 +846,32 @@ func Lookdot1(errnode ir.Node, s *types.Sym, t *types.Type, fs *types.Fields, do
|
||||
// NewMethodExpr returns an OMETHEXPR node representing method
|
||||
// expression "recv.sym".
|
||||
func NewMethodExpr(pos src.XPos, recv *types.Type, sym *types.Sym) *ir.SelectorExpr {
|
||||
n := Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(recv), sym)).(*ir.SelectorExpr)
|
||||
base.Assert(n.Op() == ir.OMETHEXPR)
|
||||
return n
|
||||
}
|
||||
|
||||
// typecheckMethodExpr checks selector expressions (ODOT) where the
|
||||
// base expression is a type expression (OTYPE).
|
||||
func typecheckMethodExpr(n *ir.SelectorExpr) (res ir.Node) {
|
||||
if base.EnableTrace && base.Flag.LowerT {
|
||||
defer tracePrint("typecheckMethodExpr", n)(&res)
|
||||
}
|
||||
|
||||
t := n.X.Type()
|
||||
|
||||
// Compute the method set for t.
|
||||
// Compute the method set for recv.
|
||||
var ms *types.Fields
|
||||
if t.IsInterface() {
|
||||
ms = t.AllMethods()
|
||||
if recv.IsInterface() {
|
||||
ms = recv.AllMethods()
|
||||
} else {
|
||||
mt := types.ReceiverBaseType(t)
|
||||
mt := types.ReceiverBaseType(recv)
|
||||
if mt == nil {
|
||||
base.Errorf("%v undefined (type %v has no method %v)", n, t, n.Sel)
|
||||
n.SetType(nil)
|
||||
return n
|
||||
base.FatalfAt(pos, "type %v has no receiver base type", recv)
|
||||
}
|
||||
CalcMethods(mt)
|
||||
ms = mt.AllMethods()
|
||||
}
|
||||
|
||||
s := n.Sel
|
||||
m := Lookdot1(n, s, t, ms, 0)
|
||||
m := Lookdot1(nil, sym, recv, ms, 0)
|
||||
if m == nil {
|
||||
if Lookdot1(n, s, t, ms, 1) != nil {
|
||||
base.Errorf("%v undefined (cannot refer to unexported method %v)", n, s)
|
||||
} else if _, ambig := dotpath(s, t, nil, false); ambig {
|
||||
base.Errorf("%v undefined (ambiguous selector)", n) // method or field
|
||||
} else {
|
||||
base.Errorf("%v undefined (type %v has no method %v)", n, t, s)
|
||||
}
|
||||
n.SetType(nil)
|
||||
return n
|
||||
base.FatalfAt(pos, "type %v has no method %v", recv, sym)
|
||||
}
|
||||
|
||||
if !types.IsMethodApplicable(t, m) {
|
||||
base.Errorf("invalid method expression %v (needs pointer receiver: (*%v).%S)", n, t, s)
|
||||
n.SetType(nil)
|
||||
return n
|
||||
if !types.IsMethodApplicable(recv, m) {
|
||||
base.FatalfAt(pos, "invalid method expression %v.%v (needs pointer receiver)", recv, sym)
|
||||
}
|
||||
|
||||
n.SetOp(ir.OMETHEXPR)
|
||||
n := ir.NewSelectorExpr(pos, ir.OMETHEXPR, ir.TypeNode(recv), sym)
|
||||
n.Selection = m
|
||||
n.SetType(NewMethodType(m.Type, n.X.Type()))
|
||||
n.SetType(NewMethodType(m.Type, recv))
|
||||
n.SetTypecheck(1)
|
||||
return n
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user