diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 59fcd5492ebde..71265bd71e18f 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -603,7 +603,18 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx())); let method_call = MethodCall::expr(call_expr.id); - let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; + let method_ty = match bcx.tcx().method_map.borrow().get(&method_call) { + Some(method) => match method.origin { + ty::MethodTraitObject(_) => match method.ty.sty { + ty::ty_bare_fn(_, ref fty) => { + ty::mk_bare_fn(bcx.tcx(), None, meth::opaque_method_ty(bcx.tcx(), fty)) + } + _ => method.ty + }, + _ => method.ty + }, + None => panic!("method not found in trans_method_call") + }; trans_call_inner( bcx, call_expr.debug_loc(), diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 3411f12886d22..69e05eaea21d2 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -589,15 +589,16 @@ pub fn trans_object_shim<'a, 'tcx>( }; let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty); let fty = tcx.mk_bare_fn(fty); - debug!("trans_object_shim: fty={}", fty.repr(tcx)); + let method_ty = opaque_method_ty(tcx, fty); + debug!("trans_object_shim: fty={} method_ty={}", fty.repr(tcx), method_ty.repr(tcx)); // - let method_bare_fn_ty = - ty::mk_bare_fn(tcx, None, fty); + let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty); + let method_bare_fn_ty = ty::mk_bare_fn(tcx, None, method_ty); let function_name = - link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim"); + link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim"); let llfn = - decl_internal_rust_fn(ccx, method_bare_fn_ty, &function_name); + decl_internal_rust_fn(ccx, shim_fn_ty, &function_name); let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig); @@ -866,3 +867,20 @@ pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx } + +/// Replace the self type (&Self or Box) with an opaque pointer. +pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>) + -> &'tcx ty::BareFnTy<'tcx> { + let mut inputs = method_ty.sig.0.inputs.clone(); + inputs[0] = ty::mk_mut_ptr(tcx, ty::mk_mach_int(tcx, ast::TyI8)); + + tcx.mk_bare_fn(ty::BareFnTy { + unsafety: method_ty.unsafety, + abi: method_ty.abi, + sig: ty::Binder(ty::FnSig { + inputs: inputs, + output: method_ty.sig.0.output, + variadic: method_ty.sig.0.variadic, + }), + }) +}