// createWrapper returns a synthetic method that delegates to the // declared method denoted by meth.Obj(), first performing any // necessary pointer indirections or field selections implied by meth. // // The resulting method's receiver type is meth.Recv(). // // This function is versatile but quite subtle! Consider the // following axes of variation when making changes: // - optional receiver indirection // - optional implicit field selections // - meth.Obj() may denote a concrete or an interface method // - the result may be a thunk or a wrapper. func createWrapper(prog *Program, sel *selection) *Function { … } // buildWrapper builds fn.Body for a method wrapper. func (b *builder) buildWrapper(fn *Function) { … } // createParams creates parameters for wrapper method fn based on its // Signature.Params, which do not include the receiver. // start is the index of the first regular parameter to use. func createParams(fn *Function, start int) { … } // createBound returns a bound method wrapper (or "bound"), a synthetic // function that delegates to a concrete or interface method denoted // by obj. The resulting function has no receiver, but has one free // variable which will be used as the method's receiver in the // tail-call. // // Use MakeClosure with such a wrapper to construct a bound method // closure. e.g.: // // type T int or: type T interface { meth() } // func (t T) meth() // var t T // f := t.meth // f() // calls t.meth() // // f is a closure of a synthetic wrapper defined as if by: // // f := func() { return t.meth() } // // Unlike createWrapper, createBound need perform no indirection or field // selections because that can be done before the closure is // constructed. func createBound(prog *Program, obj *types.Func) *Function { … } // buildBound builds fn.Body for a bound method closure. func (b *builder) buildBound(fn *Function) { … } // createThunk returns a thunk, a synthetic function that delegates to a // concrete or interface method denoted by sel.obj. The resulting // function has no receiver, but has an additional (first) regular // parameter. // // Precondition: sel.kind == types.MethodExpr. // // type T int or: type T interface { meth() } // func (t T) meth() // f := T.meth // var t T // f(t) // calls t.meth() // // f is a synthetic wrapper defined as if by: // // f := func(t T) { return t.meth() } func createThunk(prog *Program, sel *selection) *Function { … } func changeRecv(s *types.Signature, recv *types.Var) *types.Signature { … } type selection … func toSelection(sel *types.Selection) *selection { … } // buildInstantiationWrapper builds the body of an instantiation // wrapper fn. The body calls the original generic function, // bracketed by ChangeType conversions on its arguments and results. func (b *builder) buildInstantiationWrapper(fn *Function) { … }