Repository: dtolnay/cxx (language: rust)

Issue:
fn argument to extern fn warns as not FFI-safe
The ui tests started failing with a new warning on `fn` being not FFI-safe. I'll remove c_take_callback from the test suite for now to keep the ui tests active but we should fix this.

```console
EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: enums with generic parameters are not allowed
 --> $DIR/generic_enum.rs:3:5
  |
3 |     enum A<T> {
  |     ^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
warning: `extern` fn uses type `fn(std::string::String) -> usize`, which is not FFI-safe
  --> $DIR/lib.rs:67:38
   |
67 |         fn c_take_callback(callback: fn(String) -> usize);
   |                                      ^^^^^^^^^^^^^^^^^^^ not FFI-safe
   |
   = note: `#[warn(improper_ctypes_definitions)]` on by default
   = help: consider using an `extern fn(...) -> ...` function pointer instead
   = note: this function pointer has Rust-specific calling convention

warning: 1 warning emitted

error: enums with generic parameters are not allowed
 --> $DIR/generic_enum.rs:3:5
  |
3 |     enum A<T> {
  |     ^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
```


Discussion / hints:

Fix patch:
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1bcaa1e30..b25d83054 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -594,7 +594,7 @@ fn expand_rust_function_shim_impl(
                 quote!(#receiver_type::#ident)
             }
         },
-        None => quote!(__extern),
+        None => quote!(::std::mem::transmute::<*const (), #sig>(__extern)),
     };
     call.extend(quote! { (#(#vars),*) });
 
@@ -662,7 +662,7 @@ fn expand_rust_function_shim_impl(
     };
 
     let pointer = match invoke {
-        None => Some(quote!(__extern: #sig)),
+        None => Some(quote!(__extern: *const ())),
         Some(_) => None,
     };
 


Test patch:
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c79aff3d1..742062d19 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -169,10 +169,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
-        /*
-        // https://github.com/dtolnay/cxx/issues/232
         fn c_take_callback(callback: fn(String) -> usize);
-        */
         fn c_take_enum(e: Enum);
         fn c_take_ns_enum(e: AEnum);
         fn c_take_nested_ns_enum(e: ABEnum);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4abc45642..a03ec2b75 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -385,12 +385,9 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
-/*
-// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
-*/
 
 void c_take_enum(Enum e) {
   if (e == Enum::AVal) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6b1ec1ef6..e5510485c 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -134,10 +134,7 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
-/*
-// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
-*/
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
diff --git a/tests/test.rs b/tests/test.rs
index b651feb3f..a90b8fc34 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -149,8 +149,6 @@ fn test_c_take() {
     check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal));
 }
 
-/*
-// https://github.com/dtolnay/cxx/issues/232
 #[test]
 fn test_c_callback() {
     fn callback(s: String) -> usize {
@@ -162,7 +160,6 @@ fn test_c_callback() {
 
     check!(ffi::c_take_callback(callback));
 }
-*/
 
 #[test]
 fn test_c_call_r() {