Update args on supertraits of supertraits when cloning trait impls
authorMatt Corallo <git@bluematt.me>
Sun, 8 Oct 2023 05:53:25 +0000 (05:53 +0000)
committerMatt Corallo <git@bluematt.me>
Sun, 8 Oct 2023 06:53:01 +0000 (06:53 +0000)
When cloning implementations of traits from in-crate structs, we
forgot to update the arguments for supertraits of supertraits,
causing methods on that trait to be called against the previous
struct, not the cloned one.

This was ultimately identified downstream in the Java bindings,
fixes https://github.com/lightningdevkit/ldk-garbagecollected/issues/138

c-bindings-gen/src/main.rs

index c00b32d356a7865a026cc8e7f9ef5ae67837823d..22eabf7affbb53fdfb7c47a863fd4db9232e37ed 100644 (file)
@@ -1254,15 +1254,22 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, w_uses: &mut HashSet<String, NonRa
                                                        writeln!(w, "extern \"C\" fn {}_{}_cloned(new_obj: &mut crate::{}) {{", trait_obj.ident, ident, full_trait_path).unwrap();
                                                        writeln!(w, "\tnew_obj.this_arg = {}_clone_void(new_obj.this_arg);", ident).unwrap();
                                                        writeln!(w, "\tnew_obj.free = Some({}_free_void);", ident).unwrap();
-                                                       walk_supertraits!(trait_obj, Some(&types), (
-                                                               (s, t, _) => {
-                                                                       if types.crate_types.traits.get(s).is_some() {
-                                                                               assert!(!types.is_clonable(s)); // We don't currently support cloning with a clonable supertrait
-                                                                               writeln!(w, "\tnew_obj.{}.this_arg = new_obj.this_arg;", t).unwrap();
-                                                                               writeln!(w, "\tnew_obj.{}.free = None;", t).unwrap();
+
+                                                       fn seek_supertraits<W: std::io::Write>(w: &mut W, pfx: &str, tr: &syn::ItemTrait, types: &TypeResolver) {
+                                                               walk_supertraits!(tr, Some(types), (
+                                                                       (s, t, _) => {
+                                                                               if types.crate_types.traits.get(s).is_some() {
+                                                                                       assert!(!types.is_clonable(s)); // We don't currently support cloning with a clonable supertrait
+                                                                                       writeln!(w, "\tnew_obj.{}{}.this_arg = new_obj.this_arg;", pfx, t).unwrap();
+                                                                                       writeln!(w, "\tnew_obj.{}{}.free = None;", pfx, t).unwrap();
+                                                                                       let tr = types.crate_types.traits.get(s).unwrap();
+                                                                                       let resolver = get_module_type_resolver!(s, types.crate_types);
+                                                                                       seek_supertraits(w, &format!("{}.", t), tr, &resolver);
+                                                                               }
                                                                        }
-                                                               }
-                                                       ) );
+                                                               ) );
+                                                       }
+                                                       seek_supertraits(w, "", trait_obj, types);
                                                        writeln!(w, "}}").unwrap();
                                                }
                                                write!(w, "\n").unwrap();