about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Koropoff <bkoropoff@gmail.com>2014-10-16 21:53:57 -0700
committerBrian Koropoff <bkoropoff@gmail.com>2014-10-16 21:57:08 -0700
commit4a4a4347cbb6cd981cb469f142a8882c5c27e517 (patch)
tree7ee561919334d6716c45440830a1c6ef5962af23
parent1600e0b93c4edf10bce71fbb68d383827c40a153 (diff)
downloadrust-4a4a4347cbb6cd981cb469f142a8882c5c27e517.tar.gz
rust-4a4a4347cbb6cd981cb469f142a8882c5c27e517.zip
Fix translation of unboxing shim for rust-call ABI methods
When translating the unboxing shim, account for the fact that the shim
translation has already performed the necessary unboxing of input
types and values when forwarding to the shimmed function.  This
prevents ICEing or generating incorrect code.

Closes #16739
-rw-r--r--src/librustc/middle/trans/callee.rs28
-rw-r--r--src/librustc/middle/trans/type_of.rs8
2 files changed, 30 insertions, 6 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index f607dfdd17f..3bfd03da283 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -281,8 +281,32 @@ pub fn trans_unboxing_shim(bcx: Block,
     };
     let boxed_function_type =
         ty::mk_bare_fn(tcx, boxed_function_type).subst(tcx, &substs);
-    let function_type =
-        ty::mk_bare_fn(tcx, (*fty).clone()).subst(tcx, &substs);
+    let function_type = match fty.abi {
+        synabi::RustCall => {
+            // We're passing through to a RustCall ABI function, but
+            // because the shim will already perform untupling, we
+            // need to pretend the shimmed function does not use
+            // RustCall so the untupled arguments can be passed
+            // through verbatim.  This is kind of ugly.
+            let fake_ty = ty::FnSig {
+                binder_id: fty.sig.binder_id,
+                inputs: type_of::untuple_arguments_if_necessary(ccx,
+                                                                fty.sig.inputs.as_slice(),
+                                                                fty.abi),
+                output: fty.sig.output,
+                variadic: false,
+            };
+            let fake_ty = ty::BareFnTy {
+                fn_style: fty.fn_style,
+                abi: synabi::Rust,
+                sig: fake_ty,
+            };
+            ty::mk_bare_fn(tcx, fake_ty).subst(tcx, &substs)
+        }
+        _ => {
+            ty::mk_bare_fn(tcx, (*fty).clone()).subst(tcx, &substs)
+        }
+    };
 
     let function_name = ty::with_path(tcx, method_id, |path| {
         link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index e723d5af89c..9c8f051332a 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -44,10 +44,10 @@ pub fn type_of_explicit_arg(ccx: &CrateContext, arg_ty: ty::t) -> Type {
 /// Yields the types of the "real" arguments for this function. For most
 /// functions, these are simply the types of the arguments. For functions with
 /// the `RustCall` ABI, however, this untuples the arguments of the function.
-fn untuple_arguments_if_necessary(ccx: &CrateContext,
-                                  inputs: &[ty::t],
-                                  abi: abi::Abi)
-                                  -> Vec<ty::t> {
+pub fn untuple_arguments_if_necessary(ccx: &CrateContext,
+                                      inputs: &[ty::t],
+                                      abi: abi::Abi)
+                                      -> Vec<ty::t> {
     if abi != abi::RustCall {
         return inputs.iter().map(|x| (*x).clone()).collect()
     }