Repository: google/autocxx (rust)

Issue:
extern_rust_type not being generated
## Expected Behavior
Rust structures annotated with #[extern_rust_type] should be generated

## Actual Behavior
extern_rust_type annotated structs are not generated, however extern_rust_function is.

## Steps to Reproduce the Problem

1.
Add this to examples/steam-mini/src/main.rs
```
#[extern_rust_type]
struct Foo;

#[extern_rust_function]
fn foo() {}
```

2.
run `cargo build`

3.
Find that bindings for `fn foo` have been generated but not `struct Foo`.

## Specifications

- Version: v0.22.4
- Platform: macOS Monterey and Ubuntu 20.04


Pull request description:
Fix 1161
Fixes #1161, partly through better documentation.

Patch:
diff --git a/parser/src/config.rs b/parser/src/config.rs
index 8f7b599c..7c1bb39a 100644
--- a/parser/src/config.rs
+++ b/parser/src/config.rs
@@ -362,6 +362,7 @@ impl IncludeCppConfig {
             || self.is_subclass_holder(cpp_name)
             || self.is_subclass_cpp(cpp_name)
             || self.is_rust_fun(cpp_name)
+            || self.is_rust_type_name(cpp_name)
             || self.is_concrete_type(cpp_name)
             || match &self.allowlist {
                 Allowlist::Unspecified(_) => panic!("Eek no allowlist yet"),
@@ -408,10 +409,14 @@ impl IncludeCppConfig {
     }
 
     pub fn is_rust_type(&self, id: &Ident) -> bool {
+        let id_string = id.to_string();
+        self.is_rust_type_name(&id_string) || self.is_subclass_holder(&id_string)
+    }
+
+    fn is_rust_type_name(&self, possible_ty: &str) -> bool {
         self.rust_types
             .iter()
-            .any(|rt| rt.get_final_ident() == &id.to_string())
-            || self.is_subclass_holder(&id.to_string())
+            .any(|rt| rt.get_final_ident() == possible_ty)
     }
 
     fn is_rust_fun(&self, possible_fun: &str) -> bool {
diff --git a/src/lib.rs b/src/lib.rs
index 4b9f26b6..54b01a53 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -495,6 +495,12 @@ pub mod extern_rust {
     /// for instance. This will contribute to an `extern "Rust"` section of the
     /// generated `cxx` bindings, and this type will appear in the C++ header
     /// generated for use in C++.
+    ///
+    /// You will likely need to forward-declare this type within your C++ headers
+    /// before you can use it in such function signatures. autocxx can't generate
+    /// headers (with this type definition) until it's parsed your header files;
+    /// logically therefore if your header files mention one of these types
+    /// it's impossible for them to see the definition of the type.
     pub use autocxx_macro::extern_rust_type;
 
     /// Declare that a given function is a Rust function which is to be exported


Test patch:
diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs
index 8aa41360..85dae27f 100644
--- a/integration-tests/tests/integration_test.rs
+++ b/integration-tests/tests/integration_test.rs
@@ -7064,6 +7064,55 @@ fn test_rust_reference_no_autodiscover() {
     );
 }
 
+#[test]
+fn test_rust_box() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    #include <cxx.h>
+
+    struct RustType;
+    inline uint32_t take_rust_box(rust::Box<RustType>) {
+        return 4;
+    }
+    "};
+    let rs = quote! {
+        let foo = Box::new(RustType(3));
+        let result = ffi::take_rust_box(foo);
+        assert_eq!(result, 4);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(&["take_rust_box"], &[], None),
+        None,
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            pub struct RustType(i32);
+        }),
+    );
+}
+
+#[test]
+fn test_rust_reference_no_autodiscover_no_usage() {
+    let rs = quote! {
+        let _ = RustType(3);
+    };
+    run_test_ex(
+        "",
+        "",
+        rs,
+        directives_from_lists(&[], &[], None),
+        None,
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            pub struct RustType(i32);
+        }),
+    );
+}
+
 #[test]
 #[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 // TODO - replace make_clang_arg_adder with something that knows how to add an MSVC-suitable