From 8b6b3c159c0b980e340a9bb05b8a90bd9bc1dfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sun, 1 Mar 2015 18:19:07 +0100 Subject: [PATCH] Emit proper attributes for the self pointer in method call through trait objects For method calls through trait objects, we currently generate the llvm function argument attributes using the non-opaque method signature that still has the trait object fat pointer for the self pointer. This leads to attributes that are plain wrong, e.g. noalias. As we don't know anything about the concrete type of the underlying object, we must replace the self argument with an opaque i8 pointer before applying the attributes. --- src/librustc_trans/trans/callee.rs | 13 ++++++++++++- src/librustc_trans/trans/meth.rs | 28 +++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) 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, + }), + }) +}