From 0d18dbab7e8ddd4c5225d23bf5833b45eca29aa7 Mon Sep 17 00:00:00 2001 From: Taylor Foxhall Date: Sun, 30 Mar 2025 14:50:28 -0400 Subject: [PATCH] Add test for nested template types It seems that generating a type with a member function that uses a reference to a typedef of a templated type causes autocxx to interpret the typedef member as a namespace. The `extern "C++"` generated the following from the submitted test case: ```rust unsafe extern "C++" { #[cxx_name = "B"] type B = super::B; #[namespace = "B"] #[cxx_name = "F"] type B_F; } ``` Which I believe is what causes the downstream issue that gets reported in the test failure: ``` cargo:warning=/tmp/.tmpTCdyDa/target/cxx/gen0.cxx:120:11: error: 'namespace B { }' redeclared as different kind of entity cargo:warning= 120 | namespace B { cargo:warning= | ^ cargo:warning=In file included from /tmp/.tmpTCdyDa/target/cxx/gen0.cxx:1: cargo:warning=/tmp/.tmpTCdyDa/input.h:5:7: note: previous declaration 'class B' cargo:warning= 5 | class B { cargo:warning= | ^ ``` I tried poking around `RsCodeGenerator::generate_cxxbridge_type`, which is where I think the actual generation of the buggy `#[namespace = "B"]` is coming from, but I don't really understand enough about how the namespace is being parsed to suggest a fix. Maybe this is a known issue? There's some comments scattered around the source that seem to imply that some tricks are being done to handle nested types. --- integration-tests/tests/integration_test.rs | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs index 9d6590023..239aa040f 100644 --- a/integration-tests/tests/integration_test.rs +++ b/integration-tests/tests/integration_test.rs @@ -12578,6 +12578,35 @@ fn test_opaque_directive() { ); } +#[test] +fn test_templated_ref() { + let hdr = indoc! {" + template + class X; + + class B { + public: + typedef X F; + void foo(const F& x); + }; + "}; + let rs = quote! { + use autocxx::prelude::*; + let _ = ffi::Bar::new().within_unique_ptr().foo(); + }; + run_test_ex( + "", + hdr, + rs, + quote! { + generate!("B") + }, + None, + None, + None, + ); +} + // Yet to test: // - Ifdef // - Out param pointers