about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2015-10-12 21:50:57 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2015-10-12 21:54:48 +0300
commitbee664f9d0135c1e5125b5d80f44bed5d29a4584 (patch)
tree995fc4e47224f93b3fe59aab32294def82d06d33
parent843e528fd0c09666cc5f2896258f88c25eaacb29 (diff)
downloadrust-bee664f9d0135c1e5125b5d80f44bed5d29a4584.tar.gz
rust-bee664f9d0135c1e5125b5d80f44bed5d29a4584.zip
normalize the types of foreign functions
This is needed as item types are allowed to be unnormalized.

Fixes an ICE that occurs when foreign function signatures contained
an associated type.

Fixes #28983
-rw-r--r--src/librustc_trans/trans/foreign.rs12
-rw-r--r--src/test/run-pass/issue-28983.rs31
2 files changed, 36 insertions, 7 deletions
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 6b9f1559d37..95e9e8581bd 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -27,6 +27,7 @@ use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
 use trans::type_of;
+use middle::infer;
 use middle::ty::{self, Ty};
 use middle::subst::Substs;
 
@@ -254,6 +255,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         _ => ccx.sess().bug("trans_native_call called on non-function type")
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
+    let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
     let fn_type = cabi::compute_abi_info(ccx,
                                          &llsig.llarg_tys,
@@ -558,8 +560,6 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
                                          -> ValueRef {
     let _icx = push_ctxt("foreign::register_foreign_fn");
 
-    let tys = foreign_types_for_id(ccx, node_id);
-    let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let t = ccx.tcx().node_id_to_type(node_id);
     let cconv = match t.sty {
         ty::TyBareFn(_, ref fn_ty) => {
@@ -567,6 +567,8 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
         }
         _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
     };
+    let tys = foreign_types_for_fn_ty(ccx, t);
+    let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
     add_argument_attributes(&tys, llfn);
     debug!("register_rust_fn_with_foreign_abi(node_id={}, llfn_ty={}, llfn={})",
@@ -937,11 +939,6 @@ fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                  id: ast::NodeId) -> ForeignTypes<'tcx> {
-    foreign_types_for_fn_ty(ccx, ccx.tcx().node_id_to_type(id))
-}
-
 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
     let fn_sig = match ty.sty {
@@ -949,6 +946,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
+    let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs);
     let fn_ty = cabi::compute_abi_info(ccx,
                                        &llsig.llarg_tys,
diff --git a/src/test/run-pass/issue-28983.rs b/src/test/run-pass/issue-28983.rs
new file mode 100644
index 00000000000..658e9e14ee2
--- /dev/null
+++ b/src/test/run-pass/issue-28983.rs
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Test { type T; }
+
+impl Test for u32 {
+    type T = i32;
+}
+
+pub mod export {
+    #[no_mangle]
+    pub extern "C" fn issue_28983(t: <u32 as ::Test>::T) -> i32 { t*3 }
+}
+
+// to test both exporting and importing functions, import
+// a function from ourselves.
+extern "C" {
+    fn issue_28983(t: <u32 as Test>::T) -> i32;
+}
+
+fn main() {
+    assert_eq!(export::issue_28983(2), 6);
+    assert_eq!(unsafe { issue_28983(3) }, 9);
+}