Repository: google/autocxx (Rust)

Issue:
c++ function can return a struct xor take a rust::Str, but not both
## Steps to Reproduce the Problem

```rust
#[test]
fn test_pass_rust_str_and_return_struct() {
    // we can take a str
    let cxx = indoc! {"
        A return_struct() {
            A a;
            return a;
        }
    "};
    let hdr = indoc! {"
        struct A {};
        A return_struct();
    "};
    let rs = quote! {
        ffi::return_struct();
    };
    run_test(cxx, hdr, rs, &["return_struct"], &[]);

    // we can return a struct
    let cxx = indoc! {"
        void take_str(rust::Str) {}
    "};
    let hdr = indoc! {"
        #include <cxx.h>
        void take_str(rust::Str);
    "};
    let rs = quote! {
        ffi::take_str("hi");
    };
    run_test(cxx, hdr, rs, &["take_str"], &[]);

    // but we cant do both at the same time
    let cxx = indoc! {"
        A take_str_return_struct(rust::Str) {
            A a;
            return a;
        }
    "};
    let hdr = indoc! {"
        #include <cxx.h>
        struct A {};
        A take_str_return_struct(rust::Str);
    "};
    let rs = quote! {
        ffi::take_str_return_struct("hi");
    };
    run_test(cxx, hdr, rs, &["take_str_return_struct"], &[]);

    // This is the result:
    //
    // /tmp/.tmp1iMrwc/target/cxx/gen0.cxx: In function ‘A* cxxbridge1$take_str_return_struct_autocxx_wrapper(rust::cxxbridge1::Str)’:/tmp/.tmp1iMrwc/target/cxx/gen0.cxx:127:86: error:
    //   invalid conversion from ‘std::unique_ptr<A> (*)(const rust::cxxbridge1::Str&)’ to ‘std::unique_ptr<A> (*)(rust::cxxbridge1::Str)’
    //   [-fpermissive]  127
    //   ::std::unique_ptr<::A> (*take_str_return_struct_autocxx_wrapper$)(::rust::Str) = ::take_str_return_struct_autocxx_wrapper;
    //                                                                                    ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::unique_ptr<A> (*)(const rust::cxxbridge1::Str&)                                                                                                                                                                                             Replace line comments with a single block comment
    // test integration_test::test_pass_rust_str_and_return_struct ... FAILED
}
```

## Specifications

- Version: current `main`, 85d3e83f299bbf50defa34623197d6b3993592cb


Discussion:
A workaround for this is to manually wrap the returned struct in `std::unique_ptr` like so:

```c++
#include <cxx.h>
#include <memory>
struct A {};
std::unique_ptr<A> take_str_return_struct(rust::Str);
```



Patch:
diff --git a/engine/src/conversion/codegen_cpp/type_to_cpp.rs b/engine/src/conversion/codegen_cpp/type_to_cpp.rs
index 526609d2f..f762986c9 100644
--- a/engine/src/conversion/codegen_cpp/type_to_cpp.rs
+++ b/engine/src/conversion/codegen_cpp/type_to_cpp.rs
@@ -101,11 +101,14 @@ pub(crate) fn type_to_cpp(ty: &Type, cpp_name_map: &CppNameMap) -> Result<String
                 Some(suffix) => Ok(format!("{}<{}>", root, suffix)),
             }
         }
-        Type::Reference(typr) => Ok(format!(
-            "{}{}&",
-            get_mut_string(&typr.mutability),
-            type_to_cpp(typr.elem.as_ref(), cpp_name_map)?
-        )),
+        Type::Reference(typr) => match &*typr.elem {
+            Type::Path(typ) if typ.path.is_ident("str") => Ok("rust::Str".into()),
+            _ => Ok(format!(
+                "{}{}&",
+                get_mut_string(&typr.mutability),
+                type_to_cpp(typr.elem.as_ref(), cpp_name_map)?
+            )),
+        },
         Type::Ptr(typp) => Ok(format!(
             "{}{}*",
             get_mut_string(&typp.mutability),


Test patch:
diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs
index 991713ce1..c5fe078c7 100644
--- a/integration-tests/tests/integration_test.rs
+++ b/integration-tests/tests/integration_test.rs
@@ -10263,6 +10263,25 @@ fn test_doc_comments_survive() {
     );
 }
 
+#[test]
+fn test_pass_rust_str_and_return_struct() {
+    let cxx = indoc! {"
+        A take_str_return_struct(rust::Str) {
+            A a;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cxx.h>
+        struct A {};
+        A take_str_return_struct(rust::Str);
+    "};
+    let rs = quote! {
+        ffi::take_str_return_struct("hi");
+    };
+    run_test(cxx, hdr, rs, &["take_str_return_struct"], &[]);
+}
+
 // Yet to test:
 // - Ifdef
 // - Out param pointers