Repository: google/autocxx (rust)

Issue:
Problematic generation with multiple templates
I think I've found a case where autocxx mishandles multiple templates together (or it might be mishandling the default template):

```
class Thinger {
};

template <class T>
class RefPtr {
private:
    T* m_ptr;
};

class Container {
    void* data_;
};

class FakeAlloc {

};

template <typename T, typename A=FakeAlloc>
class Holder {
    A alloc;
};


typedef Holder<RefPtr<Thinger>> ThingerRefHolder;
class Problem {
public:
    ThingerRefHolder& getThingers();
};

```

This gives an error on build:

```
  cargo:warning=.../out/autocxx-build-dir/cxx/gen0.cxx: In function 'Holder_FakeAlloc_AutocxxConcrete* cxxbridge1$Problem$getThingers(Problem&)':
  cargo:warning=.../target/debug/build/repro-templvec-2d1a543db79e0eca/out/autocxx-build-dir/cxx/gen0.cxx:185:70: error: cannot convert 'ThingerRefHolder& (Problem::*)()' {aka 'Holder<RefPtr<Thinger> >& (Problem::*)()'} to 'Holder_FakeAlloc_AutocxxConcrete& (Problem::*)()' {aka 'Holder<FakeAlloc>& (Problem::*)()'} in initialization
  cargo:warning=  185 |   ::Holder_FakeAlloc_AutocxxConcrete &(::Problem::*getThingers$)() = &::Problem::getThingers;
  cargo:warning=      |                                                                      ^~~~~~~~~~~~~~~~~~~~~~~
```

I don't quite understand it, but I think the generation is skipping over the first template argument, and naming the type after only the second?


Pull request:
Fix concrete typedef dep
Builds on #1417 to fix #1413

Patch:
diff --git a/engine/src/conversion/analysis/type_converter.rs b/engine/src/conversion/analysis/type_converter.rs
index 99cd61de..40bd081a 100644
--- a/engine/src/conversion/analysis/type_converter.rs
+++ b/engine/src/conversion/analysis/type_converter.rs
@@ -372,7 +372,10 @@ impl<'a> TypeConverter<'a> {
                 }
                 let (new_tn, api) = self.get_templated_typename(&Type::Path(typ))?;
                 extra_apis.extend(api.into_iter());
-                deps.remove(&tn);
+                // Although it's tempting to remove the dep on the original type,
+                // this means we wouldn't spot cases where the original type can't
+                // be represented in C++, e.g. because it has an unused template parameter.
+                // So we keep the original dep too.
                 typ = new_tn.to_type_path();
                 deps.insert(new_tn);
             }
diff --git a/engine/src/conversion/mod.rs b/engine/src/conversion/mod.rs
index fa24d4db..57f8d9fe 100644
--- a/engine/src/conversion/mod.rs
+++ b/engine/src/conversion/mod.rs
@@ -120,7 +120,7 @@ impl<'a> BridgeConverter<'a> {
                 Self::dump_apis("parsing", &apis);
                 // Inside parse_results, we now have a list of APIs.
                 // We now enter various analysis phases.
-                // Next, convert any typedefs.
+                // First, convert any typedefs.
                 // "Convert" means replacing bindgen-style type targets
                 // (e.g. root::std::unique_ptr) with cxx-style targets (e.g. UniquePtr).
                 let apis = convert_typedef_targets(self.config, apis);


Test patch:
diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs
index 853e17b1..2bf32aad 100644
--- a/integration-tests/tests/integration_test.rs
+++ b/integration-tests/tests/integration_test.rs
@@ -12403,6 +12403,33 @@ fn test_override_typedef_fn() {
     run_test("", hdr, quote! {}, &["Foo"], &[]);
 }
 
+#[test]
+fn test_double_template_w_default() {
+    let hdr = indoc! {"
+        class Widget {};
+
+        template <class T>
+        class RefPtr {
+        private:
+            T* m_ptr;
+        };
+
+        class FakeAlloc {};
+
+        template <typename T, typename A=FakeAlloc>
+        class Holder {
+            A alloc;
+        };
+
+        typedef Holder<RefPtr<Widget>> WidgetRefHolder;
+        class Problem {
+        public:
+            WidgetRefHolder& getWidgets();
+        };
+    "};
+    run_test("", hdr, quote! {}, &["Problem"], &[]);
+}
+
 // Yet to test:
 // - Ifdef
 // - Out param pointers