// imethods returns the methods of the interface type t, sorted by name.
func imethods(t *types.Type) []*typeSig {
- if t.HasShape() && !t.IsInterface() {
- // Non-interface shape types have no methods. (There are
- // corresponding functions (created by getInstantiation) that take
- // the dictionary and the receiver of shape type as the first two
- // arguments.)
- return nil
- }
var methods []*typeSig
for _, f := range t.AllMethods().Slice() {
if f.Type.Kind() != types.TFUNC || f.Sym == nil {
// We don't need a dictionary if we are reaching a method (possibly via an
// embedded field) which is an interface method.
if !types.IsInterfaceMethod(method.Type) {
- rcvr1 := rcvr
- if rcvr1.IsPtr() {
- rcvr1 = rcvr.Elem()
- }
+ rcvr1 := deref(rcvr)
if len(rcvr1.RParams()) > 0 {
// If rcvr has rparams, remember method as generic, which
// means we need to add a dictionary to the wrapper.
generic = true
- targs := rcvr1.RParams()
- for _, t := range targs {
- if t.HasShape() {
- base.Fatalf("method on type instantiated with shapes targ:%+v rcvr:%+v", t, rcvr)
- }
+ if rcvr.HasShape() {
+ base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr)
}
}
}
return lsym
}
+ methodrcvr := method.Type.Recv().Type
// For generic methods, we need to generate the wrapper even if the receiver
// types are identical, because we want to add the dictionary.
- if !generic && types.Identical(rcvr, method.Type.Recv().Type) {
+ if !generic && types.Identical(rcvr, methodrcvr) {
return lsym
}
nthis := ir.AsNode(tfn.Type().Recv().Nname)
- methodrcvr := method.Type.Recv().Type
indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr
// generate nil pointer check for better error
// the TOC to the appropriate value for that module. But if it returns
// directly to the wrapper's caller, nothing will reset it to the correct
// value for that function.
- //
- // Disable tailcall for RegabiArgs for now. The IR does not connect the
- // arguments with the OTAILCALL node, and the arguments are not marshaled
- // correctly.
if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic {
call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
call.Args = ir.ParamNames(tfn.Type())
var call *ir.CallExpr
if generic && dot.X != nthis {
- // TODO: for now, we don't try to generate dictionary wrappers for
- // any methods involving embedded fields, because we're not
- // generating the needed dictionaries in instantiateMethods.
+ // If there is embedding involved, then we should do the
+ // normal non-generic embedding wrapper below, which calls
+ // the wrapper for the real receiver type using dot as an
+ // argument. There is no need for generic processing (adding
+ // a dictionary) for this wrapper.
generic = false
}
if generic {
- var args []ir.Node
- var targs []*types.Type
- if rcvr.IsPtr() {
- targs = rcvr.Elem().RParams()
- } else {
- targs = rcvr.RParams()
- }
+ targs := deref(rcvr).RParams()
// The wrapper for an auto-generated pointer/non-pointer
// receiver method should share the same dictionary as the
// corresponding original (user-written) method.
baseOrig := orig
- if baseOrig.IsPtr() && !method.Type.Recv().Type.IsPtr() {
+ if baseOrig.IsPtr() && !methodrcvr.IsPtr() {
baseOrig = baseOrig.Elem()
- } else if !baseOrig.IsPtr() && method.Type.Recv().Type.IsPtr() {
+ } else if !baseOrig.IsPtr() && methodrcvr.IsPtr() {
baseOrig = types.NewPtr(baseOrig)
}
- args = append(args, getDictionary(ir.MethodSym(baseOrig, method.Sym), targs))
+ args := []ir.Node{getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)}
if indirect {
args = append(args, ir.NewStarExpr(base.Pos, dot.X))
} else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() {
sym := typecheck.MakeDictSym(gf, targs, true)
- // Initialize the dictionary, if we haven't yet already.
+ // Dictionary should already have been generated by instantiateMethods().
if lsym := sym.Linksym(); len(lsym.P) == 0 {
base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
}
np.SetTypecheck(1)
return np
}
+
+func deref(t *types.Type) *types.Type {
+ if t.IsPtr() {
+ return t.Elem()
+ }
+ return t
+}