]> git.lizzy.rs Git - rust.git/commitdiff
Change type of extern fns from `*u8` to `extern "ABI" fn`
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 21 Aug 2013 13:27:48 +0000 (09:27 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 21 Aug 2013 14:50:37 +0000 (10:50 -0400)
cc #3678

26 files changed:
doc/rust.md
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/builder.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/llrepr.rs [new file with mode: 0644]
src/librustc/middle/trans/mod.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/collect.rs
src/test/auxiliary/extern-crosscrate-source.rs
src/test/compile-fail/extern-cstack-lint.rs [new file with mode: 0644]
src/test/compile-fail/extern-no-call.rs [deleted file]
src/test/compile-fail/extern-wrong-value-type.rs
src/test/run-pass/const-cast.rs
src/test/run-pass/const-cross-crate-extern.rs
src/test/run-pass/const-extern-function.rs
src/test/run-pass/extern-call-deep.rs
src/test/run-pass/extern-call-deep2.rs
src/test/run-pass/extern-call-direct.rs [new file with mode: 0644]
src/test/run-pass/extern-call-indirect.rs [new file with mode: 0644]
src/test/run-pass/extern-call-scrub.rs
src/test/run-pass/extern-call.rs [deleted file]
src/test/run-pass/extern-compare-with-return-type.rs [new file with mode: 0644]
src/test/run-pass/extern-stress.rs
src/test/run-pass/extern-take-value.rs
src/test/run-pass/extern-yield.rs
src/test/run-pass/foreign-call-no-runtime.rs

index 16927d0de7a4a48c27bea63bcc3431bbbcd37cb8..b316f889ad1e4805bb1021d25050190da227d402 100644 (file)
@@ -1006,20 +1006,25 @@ code_. They are defined in the same way as any other Rust function,
 except that they have the `extern` modifier.
 
 ~~~
+// Declares an extern fn, the ABI defaults to "C" 
 extern fn new_vec() -> ~[int] { ~[] }
+
+// Declares an extern fn with "stdcall" ABI
+extern "stdcall" fn new_vec_stdcall() -> ~[int] { ~[] }
 ~~~
 
-Extern functions may not be called from Rust code,
-but Rust code may take their value as a raw `u8` pointer.
+Unlike normal functions, extern fns have an `extern "ABI" fn()`.
+This is the same type as the functions declared in an extern
+block.
 
 ~~~
 # extern fn new_vec() -> ~[int] { ~[] }
-let fptr: *u8 = new_vec;
+let fptr: extern "C" fn() -> ~[int] = new_vec;
 ~~~
 
-The primary motivation for extern functions is
-to create callbacks for foreign functions that expect to receive function
-pointers.
+Extern functions may be called from Rust code, but
+caution must be taken with respect to the size of the stack
+segment, just as when calling an extern function normally.
 
 ### Type definitions
 
@@ -1384,14 +1389,13 @@ between the Rust ABI and the foreign ABI.
 A number of [attributes](#attributes) control the behavior of external
 blocks.
 
-By default external blocks assume
-that the library they are calling uses the standard C "cdecl" ABI.
-Other ABIs may be specified using the `abi` attribute as in
+By default external blocks assume that the library they are calling
+uses the standard C "cdecl" ABI.  Other ABIs may be specified using
+an `abi` string, as shown here:
 
 ~~~{.xfail-test}
 // Interface to the Windows API
-#[abi = "stdcall"]
-extern { }
+extern "stdcall" { }
 ~~~
 
 The `link_name` attribute allows the name of the library to be specified.
@@ -1407,6 +1411,12 @@ This is particularly useful for creating external blocks for libc,
 which tends to not follow standard library naming conventions
 and is linked to all Rust programs anyway.
 
+The type of a function
+declared in an extern block
+is `extern "abi" fn(A1, ..., An) -> R`,
+where `A1...An` are the declared types of its arguments
+and `R` is the decalred return type.
+
 ## Attributes
 
 ~~~~~~~~{.ebnf .gram}
index 50b5140505ef35ed8114a3fc1efc84a283c81035..cbd1ee1d5da48cd555e657298378d389df923974 100644 (file)
@@ -52,6 +52,7 @@
 use middle::trans::foreign;
 use middle::trans::glue;
 use middle::trans::inline;
+use middle::trans::llrepr::LlvmRepr;
 use middle::trans::machine;
 use middle::trans::machine::{llalign_of_min, llsize_of};
 use middle::trans::meth;
@@ -1740,6 +1741,10 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
                             args: &[ast::arg],
                             raw_llargs: &[ValueRef],
                             arg_tys: &[ty::t]) -> @mut Block {
+    debug!("copy_args_to_allocas: raw_llargs=%s arg_tys=%s",
+           raw_llargs.llrepr(fcx.ccx),
+           arg_tys.repr(fcx.ccx.tcx));
+
     let _icx = push_ctxt("copy_args_to_allocas");
     let mut bcx = bcx;
 
index cba7a2253952ff55989de9d882914dbfbd7d4510..9b910ab1ebc05ae395d8084bc85856aff4311110 100644 (file)
@@ -22,6 +22,7 @@
 use std::libc::{c_uint, c_ulonglong, c_char};
 use std::vec;
 use syntax::codemap::span;
+use std::ptr::is_not_null;
 
 pub struct Builder {
     llbuilder: BuilderRef,
@@ -483,6 +484,7 @@ pub fn store(&self, val: ValueRef, ptr: ValueRef) {
         debug!("Store %s -> %s",
                self.ccx.tn.val_to_str(val),
                self.ccx.tn.val_to_str(ptr));
+        assert!(is_not_null(self.llbuilder));
         self.count_insn("store");
         unsafe {
             llvm::LLVMBuildStore(self.llbuilder, val, ptr);
index 725b525233e3df01bda586dbeed3aec8000b45e0..0912e412fcf6e323ffa8fb37408dd9f249351d39 100644 (file)
@@ -824,56 +824,30 @@ fn trans_def_datum_unadjusted(bcx: @mut Block,
 {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
-    match def {
+    let fn_data = match def {
         ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
-            let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id);
-            return fn_data_to_datum(bcx, ref_expr, did, fn_data);
+            callee::trans_fn_ref(bcx, did, ref_expr.id)
         }
         ast::def_static_method(impl_did, Some(trait_did), _) => {
-            let fn_data = meth::trans_static_method_callee(bcx, impl_did,
-                                                           trait_did,
-                                                           ref_expr.id);
-            return fn_data_to_datum(bcx, ref_expr, impl_did, fn_data);
+            meth::trans_static_method_callee(bcx, impl_did,
+                                             trait_did,
+                                             ref_expr.id)
         }
         _ => {
             bcx.tcx().sess.span_bug(ref_expr.span, fmt!(
                 "Non-DPS def %? referened by %s",
                 def, bcx.node_id_to_str(ref_expr.id)));
         }
-    }
+    };
 
-    fn fn_data_to_datum(bcx: @mut Block,
-                        ref_expr: &ast::expr,
-                        def_id: ast::def_id,
-                        fn_data: callee::FnData) -> DatumBlock {
-        /*!
-        *
-        * Translates a reference to a top-level fn item into a rust
-        * value.  This is just a fn pointer.
-        */
-
-        let is_extern = {
-            let fn_tpt = ty::lookup_item_type(bcx.tcx(), def_id);
-            ty::ty_fn_purity(fn_tpt.ty) == ast::extern_fn
-        };
-        let (rust_ty, llval) = if is_extern {
-            let rust_ty = ty::mk_ptr(
-                bcx.tcx(),
-                ty::mt {
-                    ty: ty::mk_mach_uint(ast::ty_u8),
-                    mutbl: ast::m_imm
-                }); // *u8
-            (rust_ty, PointerCast(bcx, fn_data.llfn, Type::i8p()))
-        } else {
-            let fn_ty = expr_ty(bcx, ref_expr);
-            (fn_ty, fn_data.llfn)
-        };
-        return DatumBlock {
-            bcx: bcx,
-            datum: Datum {val: llval,
-                          ty: rust_ty,
-                          mode: ByValue}
-        };
+    let fn_ty = expr_ty(bcx, ref_expr);
+    DatumBlock {
+        bcx: bcx,
+        datum: Datum {
+            val: fn_data.llfn,
+            ty: fn_ty,
+            mode: ByValue
+        }
     }
 }
 
@@ -1657,6 +1631,7 @@ pub fn cast_type_kind(t: ty::t) -> cast_kind {
         ty::ty_float(*)   => cast_float,
         ty::ty_ptr(*)     => cast_pointer,
         ty::ty_rptr(*)    => cast_pointer,
+        ty::ty_bare_fn(*) => cast_pointer,
         ty::ty_int(*)     => cast_integral,
         ty::ty_uint(*)    => cast_integral,
         ty::ty_bool       => cast_integral,
@@ -1719,10 +1694,16 @@ fn trans_imm_cast(bcx: @mut Block, expr: @ast::expr,
                                               val_ty(lldiscrim_a),
                                               lldiscrim_a, true),
                     cast_float => SIToFP(bcx, lldiscrim_a, ll_t_out),
-                    _ => ccx.sess.bug("translating unsupported cast.")
+                    _ => ccx.sess.bug(fmt!("translating unsupported cast: \
+                                           %s (%?) -> %s (%?)",
+                                           t_in.repr(ccx.tcx), k_in,
+                                           t_out.repr(ccx.tcx), k_out))
                 }
             }
-            _ => ccx.sess.bug("translating unsupported cast.")
+            _ => ccx.sess.bug(fmt!("translating unsupported cast: \
+                                   %s (%?) -> %s (%?)",
+                                   t_in.repr(ccx.tcx), k_in,
+                                   t_out.repr(ccx.tcx), k_out))
         };
     return immediate_rvalue_bcx(bcx, newval, t_out);
 }
diff --git a/src/librustc/middle/trans/llrepr.rs b/src/librustc/middle/trans/llrepr.rs
new file mode 100644 (file)
index 0000000..43fd662
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2012 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.
+
+use middle::trans::context::CrateContext;
+use middle::trans::type_::Type;
+use lib::llvm::ValueRef;
+
+pub trait LlvmRepr {
+    fn llrepr(&self, ccx: &CrateContext) -> ~str;
+}
+
+impl<'self, T:LlvmRepr> LlvmRepr for &'self [T] {
+    fn llrepr(&self, ccx: &CrateContext) -> ~str {
+        let reprs = self.map(|t| t.llrepr(ccx));
+        fmt!("[%s]", reprs.connect(","))
+    }
+}
+
+impl LlvmRepr for Type {
+    fn llrepr(&self, ccx: &CrateContext) -> ~str {
+        ccx.tn.type_to_str(*self)
+    }
+}
+
+impl LlvmRepr for ValueRef {
+    fn llrepr(&self, ccx: &CrateContext) -> ~str {
+        ccx.tn.val_to_str(*self)
+    }
+}
+
+
index cf6d465cb820c50f230e222cac3b3f3d7f73091f..008da7f7ff8f26d8b1f1b0c0a761499d076485be 100644 (file)
@@ -45,3 +45,4 @@
 pub mod type_;
 pub mod value;
 pub mod basic_block;
+pub mod llrepr;
index ad6bf69d55ad6c22a439223bf7ab86efc8be2569..7d1b5f7e93f145c3276f6dce27d57ba7eb65e351 100644 (file)
@@ -3099,22 +3099,6 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
           let typ = fcx.local_ty(sp, nid);
           return no_params(typ);
       }
-      ast::def_fn(_, ast::extern_fn) => {
-        // extern functions are just u8 pointers
-        return ty_param_bounds_and_ty {
-            generics: ty::Generics {
-                type_param_defs: @~[],
-                region_param: None
-            },
-            ty: ty::mk_ptr(
-                fcx.ccx.tcx,
-                ty::mt {
-                    ty: ty::mk_mach_uint(ast::ty_u8),
-                    mutbl: ast::m_imm
-                })
-        };
-      }
-
       ast::def_fn(id, _) | ast::def_static_method(id, _, _) |
       ast::def_static(id, _) | ast::def_variant(_, id) |
       ast::def_struct(id) => {
index 7678a12b78a5f2ad34d164751bf627eb2ca482e0..6d577d382322ab3da13ea603c92a722751f91562 100644 (file)
@@ -1067,13 +1067,13 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item)
         tcx.tcache.insert(local_def(it.id), tpt);
         return tpt;
       }
-      ast::item_fn(ref decl, purity, _, ref generics, _) => {
+      ast::item_fn(ref decl, purity, abi, ref generics, _) => {
         assert!(rp.is_none());
         let ty_generics = ty_generics(ccx, None, generics, 0);
         let tofd = astconv::ty_of_bare_fn(ccx,
                                           &empty_rscope,
                                           purity,
-                                          AbiSet::Rust(),
+                                          abi,
                                           &generics.lifetimes,
                                           decl);
         let tpt = ty_param_bounds_and_ty {
index 03cb96a3729af21dc9295d761534fde3f81f583c..e34fb610e0605470c7704ee17dabd2d688136b9f 100644 (file)
@@ -19,7 +19,8 @@ pub mod rustrt {
     use std::libc;
 
     extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
+        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
                              -> libc::uintptr_t;
     }
 }
diff --git a/src/test/compile-fail/extern-cstack-lint.rs b/src/test/compile-fail/extern-cstack-lint.rs
new file mode 100644 (file)
index 0000000..8ccd923
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2012 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.
+
+extern fn f() {
+}
+
+extern fn call1() {
+    f(); // OK from another extern fn!
+}
+
+fn call2() {
+    f(); //~ ERROR invoking non-Rust fn
+}
+
+
+fn main() {}
diff --git a/src/test/compile-fail/extern-no-call.rs b/src/test/compile-fail/extern-no-call.rs
deleted file mode 100644 (file)
index 58649f3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2012 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.
-
-// error-pattern:expected function but found `*u8`
-extern fn f() {
-}
-
-fn main() {
-    f();
-}
index fbb0f6e46a1c4a8b2a553c31050eb13b362e2469..069c5a77c6c330ffb439019ea3b487cfbc494df3 100644 (file)
@@ -12,6 +12,7 @@
 }
 
 fn main() {
-    // extern functions are *u8 types
-    let _x: &fn() = f; //~ ERROR found `*u8`
+    // extern functions are extern "C" fn
+    let _x: extern "C" fn() = f; // OK
+    let _x: &fn() = f; //~ ERROR mismatched types
 }
index 280fe44c3da3eafcf1852c0d64e6e705988cb046..d511930c70fa7a3add33363b8f61e0fd4fd335df 100644 (file)
@@ -12,7 +12,7 @@
 
 extern fn foo() {}
 
-static x: *u8 = foo;
+static x: extern "C" fn() = foo;
 static y: *libc::c_void = x as *libc::c_void;
 static a: &'static int = &10;
 static b: *int = a as *int;
index 5281c217626895dd0255226bafc784f34b7d17ad..eb7ae3d6fec99bdedf2736df02c3a696e3d61192 100644 (file)
 
 extern mod cci_const;
 use cci_const::bar;
-static foo: *u8 = bar;
+use std::cast::transmute;
+static foo: extern "C" fn() = bar;
 
 pub fn main() {
-    assert_eq!(foo, cci_const::bar);
+    unsafe {
+        assert_eq!(foo, bar);
+    }
 }
index 9a8104cb14f719a3d2281dc3f424e21c7c9be4c1..e07af4b0383fd1375f0eb2a8db4be96521e4e5ae 100644 (file)
 
 extern fn foopy() {}
 
-static f: *u8 = foopy;
+static f: extern "C" fn() = foopy;
 static s: S = S { f: foopy };
 
 struct S {
-    f: *u8
+    f: extern "C" fn()
 }
 
 pub fn main() {
-    assert_eq!(foopy, f);
-    assert_eq!(f, s.f);
+    unsafe {
+        assert_eq!(foopy, f);
+        assert_eq!(f, s.f);
+    }
 }
index 27ad2fc46e07dab407a2c9e2b3b055917b7f696b..1153cb4177daaec5e43ab6b8b1e130da8f5eda9c 100644 (file)
@@ -14,7 +14,8 @@ mod rustrt {
     use std::libc;
 
     extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
+        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
                              -> libc::uintptr_t;
     }
 }
index 6c90443636d3913cabe7008e469bdbf99697426f..a8fa9c2cef028aaa55ceb26c5fe440d0f0673fb5 100644 (file)
@@ -15,7 +15,8 @@ mod rustrt {
     use std::libc;
 
     extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
+        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
                              -> libc::uintptr_t;
     }
 }
diff --git a/src/test/run-pass/extern-call-direct.rs b/src/test/run-pass/extern-call-direct.rs
new file mode 100644 (file)
index 0000000..bc6ee63
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2012 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.
+
+// Test direct calls to extern fns.
+
+extern fn f(x: uint) -> uint { x * 2 }
+
+fn main() {
+    #[fixed_stack_segment];
+
+    let x = f(22);
+    assert_eq!(x, 44);
+}
diff --git a/src/test/run-pass/extern-call-indirect.rs b/src/test/run-pass/extern-call-indirect.rs
new file mode 100644 (file)
index 0000000..9929cb4
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2012 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.
+
+use std::libc;
+
+mod rustrt {
+    use std::libc;
+
+    extern {
+        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
+                             -> libc::uintptr_t;
+    }
+}
+
+extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1u {
+        data
+    } else {
+        fact(data - 1u) * data
+    }
+}
+
+#[fixed_stack_segment] #[inline(never)]
+fn fact(n: uint) -> uint {
+    unsafe {
+        info!("n = %?", n);
+        rustrt::rust_dbg_call(cb, n)
+    }
+}
+
+pub fn main() {
+    let result = fact(10u);
+    info!("result = %?", result);
+    assert_eq!(result, 3628800u);
+}
index 5abd3c7b9d918ce55865b555aaa1c6ebe4cfa5de..4388ef65e986548436fa3314c81d365b919a2f3f 100644 (file)
@@ -19,7 +19,8 @@ mod rustrt {
     use std::libc;
 
     extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
+        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
                              -> libc::uintptr_t;
     }
 }
diff --git a/src/test/run-pass/extern-call.rs b/src/test/run-pass/extern-call.rs
deleted file mode 100644 (file)
index 939487d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2012 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.
-
-use std::libc;
-
-mod rustrt {
-    use std::libc;
-
-    extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
-                             -> libc::uintptr_t;
-    }
-}
-
-extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1u {
-        data
-    } else {
-        fact(data - 1u) * data
-    }
-}
-
-#[fixed_stack_segment] #[inline(never)]
-fn fact(n: uint) -> uint {
-    unsafe {
-        info!("n = %?", n);
-        rustrt::rust_dbg_call(cb, n)
-    }
-}
-
-pub fn main() {
-    let result = fact(10u);
-    info!("result = %?", result);
-    assert_eq!(result, 3628800u);
-}
diff --git a/src/test/run-pass/extern-compare-with-return-type.rs b/src/test/run-pass/extern-compare-with-return-type.rs
new file mode 100644 (file)
index 0000000..41bf4a1
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2013 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.
+
+// Tests that we can compare various kinds of extern fn signatures.
+
+extern fn voidret1() {}
+extern fn voidret2() {}
+
+extern fn uintret() -> uint { 22 }
+
+extern fn uintvoidret(x: uint) {}
+
+extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z }
+
+fn main() {
+    assert_eq!(voidret1, voidret1);
+    assert!(voidret1 != voidret2);
+
+    assert_eq!(uintret, uintret);
+
+    assert_eq!(uintvoidret, uintvoidret);
+
+    assert_eq!(uintuintuintuintret, uintuintuintuintret);
+}
+
index 4eda3f34b6c15198a9f78d15d7b7efc22542a9b7..2323567ccce4360385bdd5447cdb54d93775d129 100644 (file)
@@ -18,7 +18,8 @@ mod rustrt {
     use std::libc;
 
     extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
+        pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
                              -> libc::uintptr_t;
     }
 }
index 542686c9099f1d1f469ce8f034de1cfad95c94b2..e636f511da8d309620b59c4c114a475e2bfa682d 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::cast::transmute;
+
 extern fn f() {
 }
 
 }
 
 pub fn main() {
-    // extern functions are *u8 types
-    let a: *u8 = f;
-    let b: *u8 = f;
-    let c: *u8 = g;
+    unsafe {
+        let a: extern "C" fn() = f;
+        let b: extern "C" fn() = f;
+        let c: extern "C" fn() = g;
 
-    assert_eq!(a, b);
-    assert!(a != c);
+        assert_eq!(a, b);
+        assert!(a != c);
+    }
 }
index ce51aafa9d80960160f663f1544535643ca5cb7f..fd0807dffc84c06029dd0b7a7eef9f943f4a15ec 100644 (file)
@@ -15,7 +15,8 @@ mod rustrt {
     use std::libc;
 
     extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
+        pub fn rust_dbg_call(cb: extern "C" fn (libc::uintptr_t) -> libc::uintptr_t,
+                             data: libc::uintptr_t)
                              -> libc::uintptr_t;
     }
 }
index c8acdbf44781c64bebe81228a742f753337d36ee..2fa4f191ed14d759c8f67e9b6d0ead54dd69ac4c 100644 (file)
@@ -2,7 +2,8 @@
 use std::libc;
 use std::unstable::run_in_bare_thread;
 
-externfn!(fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) -> libc::uintptr_t)
+externfn!(fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
+                           data: libc::uintptr_t) -> libc::uintptr_t)
 
 pub fn main() {
     unsafe {