// only be fully transformed once it has an instantiated type.
n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
typed(g.typ(typ), n)
+
+ // Fill in n.Selection for a generic method reference, even though we
+ // won't use it directly, since it is useful for analysis.
+ // Specifically do not fill in for fields or interfaces methods, so
+ // n.Selection being non-nil means a method reference, rather than an
+ // interface reference or reference to a field with a function value.
+ obj2 := g.info.Selections[expr].Obj()
+ sig := types2.AsSignature(obj2.Type())
+ if sig == nil || sig.Recv() == nil {
+ return n
+ }
+ // recvType is the type of the last embedded field. Because of the
+ // way methods are imported, g.obj(obj2) doesn't work across
+ // packages, so we have to lookup the method via the receiver type.
+ recvType := deref2(sig.Recv().Type())
+ if types2.AsInterface(recvType.Underlying()) != nil {
+ return n
+ }
+
+ index := g.info.Selections[expr].Index()
+ last := index[len(index)-1]
+ recvObj := types2.AsNamed(recvType).Obj()
+ recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def
+ n.Selection = recv.Type().Methods().Index(last)
return n
}
// getTargs gets the targs associated with the receiver of a selected method
func getTargs(selinfo *types2.Selection) []types2.Type {
- r := selinfo.Recv()
- if p := types2.AsPointer(r); p != nil {
- r = p.Elem()
- }
+ r := deref2(selinfo.Recv())
n := types2.AsNamed(r)
if n == nil {
base.Fatalf("Incorrect type for selinfo %v", selinfo)
if n.Op() == ir.OCALL {
call := n.(*ir.CallExpr)
if call.X.Op() == ir.OXDOT {
- subtargs := deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()
+ subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams()
s2targs := make([]*types.Type, len(subtargs))
for i, t := range subtargs {
s2targs[i] = subst.Typ(t)
}
- sym = typecheck.MakeDictName(ir.MethodSym(call.X.(*ir.SelectorExpr).X.Type(), call.X.(*ir.SelectorExpr).Sel), s2targs, true)
+ nameNode := call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name)
+ sym = g.getDictionarySym(nameNode, s2targs, true)
} else {
- inst := n.(*ir.CallExpr).X.(*ir.InstExpr)
+ inst := call.X.(*ir.InstExpr)
var nameNode *ir.Name
var meth *ir.SelectorExpr
var isMeth bool
for i, t := range subtargs {
s2targs[i] = subst.Typ(t)
}
- sym = typecheck.MakeDictName(ir.MethodSym(selExpr.X.Type(), selExpr.Sel), s2targs, true)
+ nameNode := selExpr.Selection.Nname.(*ir.Name)
+ sym = g.getDictionarySym(nameNode, s2targs, true)
}
// TODO: handle closure cases that need sub-dictionaries, get rid of conditional
if sym != nil {
- // TODO: uncomment once we're sure all the
- // subdictionaries are created correctly.
- // Methods above aren't yet generating dictionaries recursively yet.
- //off = objw.SymPtr(lsym, off, sym.Linksym(), 0)
+ off = objw.SymPtr(lsym, off, sym.Linksym(), 0)
infoPrint(" - Subdict %v\n", sym.Name)
}
}
infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X)
info.subDictCalls = append(info.subDictCalls, n)
} else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() &&
- !n.(*ir.SelectorExpr).X.Type().IsInterface() &&
+ n.(*ir.SelectorExpr).Selection != nil &&
len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 {
- // Fix this - doesn't account for embedded fields, etc.
- field := typecheck.Lookdot1(n.(*ir.SelectorExpr), n.(*ir.SelectorExpr).Sel, n.(*ir.SelectorExpr).X.Type(), n.(*ir.SelectorExpr).X.Type().Fields(), 0)
- if field == nil {
- if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE {
- infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n)
- } else {
- infoPrint(" Closure&subdictionary required at generic meth value %v\n", n)
- }
- info.subDictCalls = append(info.subDictCalls, n)
+ if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE {
+ infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n)
+ } else {
+ infoPrint(" Closure&subdictionary required at generic meth value %v\n", n)
}
+ info.subDictCalls = append(info.subDictCalls, n)
}
if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST {
infoPrint(" Subdictionary at generic function call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n)
info.subDictCalls = append(info.subDictCalls, n)
}
if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT &&
- !n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type().IsInterface() &&
+ n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil &&
len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 {
infoPrint(" Subdictionary at generic method call: %v\n", n)
n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true)