// prepareCall determines the function value and argument values for a // function call in a Call, Go or Defer instruction, peforming // interface method lookup if needed. // func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) { if call.Func != nil { // Function call. fn = fr.get(call.Func) } else { // Interface method invocation. recv := fr.get(call.Recv).(iface) if recv.t == nil { panic("method invoked on nil interface") } meth := underlyingType(call.Recv.Type()).(*types.Interface).Methods[call.Method] id := ssa.IdFromQualifiedName(meth.QualifiedName) m := findMethodSet(fr.i, recv.t)[id] if m == nil { // Unreachable in well-typed programs. panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, id)) } _, aptr := recv.v.(*value) // actual pointerness _, fptr := m.Signature.Recv.Type.(*types.Pointer) // formal pointerness switch { case aptr == fptr: args = append(args, copyVal(recv.v)) case aptr: // Calling func(T) with a *T receiver: make a copy. args = append(args, copyVal(*recv.v.(*value))) case fptr: panic("illegal call of *T method with T receiver") } fn = m } for _, arg := range call.Args { args = append(args, fr.get(arg)) } return }
// checkInterface checks that the method set of x implements the // interface itype. // On success it returns "", on failure, an error message. // func checkInterface(i *interpreter, itype types.Type, x iface) string { mset := findMethodSet(i, x.t) for _, m := range underlyingType(itype).(*types.Interface).Methods { id := ssa.IdFromQualifiedName(m.QualifiedName) if mset[id] == nil { return fmt.Sprintf("interface conversion: %v is not %v: missing method %v", x.t, itype, id) } } return "" // ok }