Repository: dtolnay/cxx (language: rust)

Issue:
Bug when defining methods on shared structs
```rust
// str_test.rs
#[cxx::bridge]
mod ffi {
    struct A {
        a: f32,
    }

    extern "Rust"{
        fn hello(self: &A) -> String;
    }
}
```

Then run 
```bash
cxxbridge str_test.rs
```

We get:
```cpp
...

::rust::String A::hello() const noexcept {
  ::rust::MaybeUninit<::rust::String> return$;
  cxxbridge05$A$hello(*this&return$.value);
  return ::std::move(return$.value);
}
```

Note that there's a missing "," in hello invocation.
It should be `cxxbridge05$A$hello(*this, &return$.value);` instead of `cxxbridge05$A$hello(*this&return$.value);`


<!--  ❤️  -->


Discussion / hints:

Fix patch:
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 39053a12a..69b9f2eb6 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -698,11 +698,13 @@ fn write_rust_function_shim_impl(
         write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
+    let mut needs_comma = false;
     if sig.receiver.is_some() {
         write!(out, "*this");
+        needs_comma = true;
     }
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 || sig.receiver.is_some() {
+    for arg in &sig.args {
+        if needs_comma {
             write!(out, ", ");
         }
         match &arg.ty {
@@ -725,15 +727,17 @@ fn write_rust_function_shim_impl(
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
+        needs_comma = true;
     }
     if indirect_return {
-        if !sig.args.is_empty() {
+        if needs_comma {
             write!(out, ", ");
         }
         write!(out, "&return$.value");
+        needs_comma = true;
     }
     if indirect_call {
-        if !sig.args.is_empty() || indirect_return {
+        if needs_comma {
             write!(out, ", ");
         }
         write!(out, "extern$");


Test patch:
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 96f9b079e..7461d66fe 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -274,7 +274,7 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
-        fn r_method_on_shared(self: &Shared) -> usize;
+        fn r_method_on_shared(self: &Shared) -> String;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -318,8 +318,8 @@ impl R2 {
 }
 
 impl ffi::Shared {
-    fn r_method_on_shared(&self) -> usize {
-        2020
+    fn r_method_on_shared(&self) -> String {
+        "2020".to_owned()
     }
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index fd4751ebe..c3c797ad8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -626,7 +626,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->get() == 2021);
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
-  ASSERT(Shared{0}.r_method_on_shared() == 2020);
+  ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");