XXX: Hax on Hax on Hax
[ldk-c-bindings] / c-bindings-gen / src / types.rs
index fc832f8ef7f212e5e18dd3f07a92ab521bf26297..cc960232d9e0424a092856b1b53978030119f22d 100644 (file)
@@ -137,7 +137,7 @@ pub fn export_status(attrs: &[syn::Attribute]) -> ExportStatus {
 }
 
 pub fn assert_simple_bound(bound: &syn::TraitBound) {
-       if bound.paren_token.is_some() || bound.lifetimes.is_some() { unimplemented!(); }
+       if bound.paren_token.is_some() { unimplemented!(); }
        if let syn::TraitBoundModifier::Maybe(_) = bound.modifier { unimplemented!(); }
 }
 
@@ -258,9 +258,11 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> {
                                                if p.qself.is_some() { return false; }
                                                if p.path.leading_colon.is_some() { return false; }
                                                let mut p_iter = p.path.segments.iter();
-                                               if let Some(gen) = new_typed_generics.get_mut(&p_iter.next().unwrap().ident) {
-                                                       if gen.is_some() { return false; }
-                                                       if &format!("{}", p_iter.next().unwrap().ident) != "Target" {return false; }
+let theident = &p_iter.next().unwrap().ident;
+eprintln!("Doing bound resolution on {}", theident);
+                                               if let Some(gen) = new_typed_generics.get_mut(theident) {
+                                                       if gen.is_some() { eprintln!("5"); return false; }
+                                                       if &format!("{}", p_iter.next().unwrap().ident) != "Target" {eprintln!("6"); return false; }
 
                                                        let mut non_lifetimes_processed = false;
                                                        for bound in t.bounds.iter() {
@@ -274,8 +276,13 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> {
                                                                        *gen = Some(types.resolve_path(&trait_bound.path, None));
                                                                }
                                                        }
-                                               } else { return false; }
-                                       } else { return false; }
+                                               } else {
+                                                       for bound in t.bounds.iter() {
+eprintln!("XXX LULZZZZZZZZZZZZZZZZZZZZ {}", theident);
+                                                               new_typed_generics.insert(theident, Some("lightning_invoice::payment::Router".to_string()));
+                                                       }
+                                               }
+                                       } else { eprintln!("9"); return false; }
                                }
                        }
                }
@@ -294,23 +301,28 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> {
                                &syn::TraitItem::Type(ref t) => {
                                        if t.default.is_some() || t.generics.lt_token.is_some() { unimplemented!(); }
                                        let mut bounds_iter = t.bounds.iter();
-                                       match bounds_iter.next().unwrap() {
-                                               syn::TypeParamBound::Trait(tr) => {
-                                                       assert_simple_bound(&tr);
-                                                       if let Some(path) = types.maybe_resolve_path(&tr.path, None) {
-                                                               if types.skip_path(&path) { continue; }
-                                                               // In general we handle Deref<Target=X> as if it were just X (and
-                                                               // implement Deref<Target=Self> for relevant types). We don't
-                                                               // bother to implement it for associated types, however, so we just
-                                                               // ignore such bounds.
-                                                               if path != "std::ops::Deref" && path != "core::ops::Deref" {
-                                                                       self.typed_generics.insert(&t.ident, path);
+                                       loop {
+                                               match bounds_iter.next().unwrap() {
+                                                       syn::TypeParamBound::Trait(tr) => {
+                                                               assert_simple_bound(&tr);
+                                                               if let Some(path) = types.maybe_resolve_path(&tr.path, None) {
+                                                                       if types.skip_path(&path) { continue; }
+                                                                       // In general we handle Deref<Target=X> as if it were just X (and
+                                                                       // implement Deref<Target=Self> for relevant types). We don't
+                                                                       // bother to implement it for associated types, however, so we just
+                                                                       // ignore such bounds.
+                                                                       if path != "std::ops::Deref" && path != "core::ops::Deref" {
+                                                                               self.typed_generics.insert(&t.ident, path);
+                                                                       }
+                                                               } else { unimplemented!(); }
+                                                               for bound in bounds_iter {
+                                                                       if let syn::TypeParamBound::Trait(_) = bound { unimplemented!(); }
                                                                }
-                                                       } else { unimplemented!(); }
-                                               },
-                                               _ => unimplemented!(),
+                                                               break;
+                                                       },
+                                                       syn::TypeParamBound::Lifetime(_) => {},
+                                               }
                                        }
-                                       if bounds_iter.next().is_some() { unimplemented!(); }
                                },
                                _ => {},
                        }
@@ -1339,7 +1351,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                Some(("Vec::new(); for mut item in ", vec![(format!(".drain(..) {{ local_{}.push(", var_name), "item".to_string())], "); }", ContainerPrefixLocation::PerConv))
                        },
                        "Slice" => {
-                               Some(("Vec::new(); for item in ", vec![(format!(".iter() {{ local_{}.push(", var_name), "item".to_string())], "); }", ContainerPrefixLocation::PerConv))
+                               if let Some(syn::Type::Reference(_)) = single_contained {
+                                       Some(("Vec::new(); for item in ", vec![(format!(".iter() {{ local_{}.push(", var_name), "(*item)".to_string())], "); }", ContainerPrefixLocation::PerConv))
+                               } else {
+                                       Some(("Vec::new(); for item in ", vec![(format!(".iter() {{ local_{}.push(", var_name), "item".to_string())], "); }", ContainerPrefixLocation::PerConv))
+                               }
                        },
                        "Option" => {
                                let contained_struct = if let Some(syn::Type::Path(p)) = single_contained {
@@ -1941,8 +1957,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                DeclType::MirroredEnum if is_ref && ptr_for_ref => write!(w, "crate::{}::from_native(", decl_path).unwrap(),
                                                DeclType::MirroredEnum if is_ref => write!(w, "&crate::{}::from_native(", decl_path).unwrap(),
                                                DeclType::MirroredEnum => write!(w, "crate::{}::native_into(", decl_path).unwrap(),
-                                               DeclType::EnumIgnored {..}|DeclType::StructImported {..} if is_ref && ptr_for_ref && from_ptr =>
-                                                       write!(w, "crate::{} {{ inner: unsafe {{ (", decl_path).unwrap(),
+                                               DeclType::EnumIgnored {..}|DeclType::StructImported {..} if is_ref && from_ptr => {
+                                                       if !ptr_for_ref { write!(w, "&").unwrap(); }
+                                                       write!(w, "crate::{} {{ inner: unsafe {{ (", decl_path).unwrap()
+                                               },
                                                DeclType::EnumIgnored {..}|DeclType::StructImported {..} if is_ref => {
                                                        if !ptr_for_ref { write!(w, "&").unwrap(); }
                                                        write!(w, "crate::{} {{ inner: unsafe {{ ObjOps::nonnull_ptr_to_inner((", decl_path).unwrap()
@@ -1968,7 +1986,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        DeclType::EnumIgnored { generic_param_count }|DeclType::StructImported { generic_param_count } if is_ref => {
                                                write!(w, " as *const {}<", full_path).unwrap();
                                                for _ in 0..*generic_param_count { write!(w, "_, ").unwrap(); }
-                                               if ptr_for_ref && from_ptr {
+                                               if from_ptr {
                                                        write!(w, ">) as *mut _ }}, is_owned: false }}").unwrap();
                                                } else {
                                                        write!(w, ">) as *mut _) }}, is_owned: false }}").unwrap();
@@ -2065,7 +2083,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                VP: Fn(&mut W, &syn::Type, Option<&GenericTypes>, bool, bool, bool),
                VS: Fn(&mut W, &syn::Type, Option<&GenericTypes>, bool, bool, bool)>
                        (&self, w: &mut W, ident: &syn::Ident, var: &str, t: &syn::Type, generics: Option<&GenericTypes>,
-                        mut is_ref: bool, mut ptr_for_ref: bool, to_c: bool,
+                        mut is_ref: bool, mut ptr_for_ref: bool, to_c: bool, from_ownable_ref: bool,
                         path_lookup: &LP, container_lookup: &LC, var_prefix: &VP, var_suffix: &VS) -> bool {
 
                macro_rules! convert_container {
@@ -2112,7 +2130,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                // If the inner element contains an inner pointer, we will just use that,
                                                // avoiding the need to map elements to references. Otherwise we'll need to
                                                // do an extra mapping step.
-                                               needs_ref_map = !only_contained_has_inner;
+                                               needs_ref_map = !only_contained_has_inner && $container_type == "Option";
                                        } else {
                                                only_contained_type = Some(arg);
                                                only_contained_type_nonref = Some(arg);
@@ -2138,7 +2156,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                write!(w, "{} {{ ", pfx).unwrap();
                                                let new_var_name = format!("{}_{}", ident, idx);
                                                let new_var = self.write_conversion_new_var_intern(w, &format_ident!("{}", new_var_name),
-                                                               &var_access, conv_ty, generics, contains_slice || (is_ref && ty_has_inner), ptr_for_ref, to_c, path_lookup, container_lookup, var_prefix, var_suffix);
+                                                               &var_access, conv_ty, generics, contains_slice || (is_ref && ty_has_inner), ptr_for_ref,
+                                                               to_c, from_ownable_ref, path_lookup, container_lookup, var_prefix, var_suffix);
                                                if new_var { write!(w, " ").unwrap(); }
 
                                                if prefix_location == ContainerPrefixLocation::PerConv {
@@ -2177,9 +2196,9 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                match generics.resolve_type(t) {
                        syn::Type::Reference(r) => {
                                if let syn::Type::Slice(_) = &*r.elem {
-                                       self.write_conversion_new_var_intern(w, ident, var, &*r.elem, generics, is_ref, ptr_for_ref, to_c, path_lookup, container_lookup, var_prefix, var_suffix)
+                                       self.write_conversion_new_var_intern(w, ident, var, &*r.elem, generics, is_ref, ptr_for_ref, to_c, from_ownable_ref, path_lookup, container_lookup, var_prefix, var_suffix)
                                } else {
-                                       self.write_conversion_new_var_intern(w, ident, var, &*r.elem, generics, true, ptr_for_ref, to_c, path_lookup, container_lookup, var_prefix, var_suffix)
+                                       self.write_conversion_new_var_intern(w, ident, var, &*r.elem, generics, true, ptr_for_ref, to_c, from_ownable_ref, path_lookup, container_lookup, var_prefix, var_suffix)
                                }
                        },
                        syn::Type::Path(p) => {
@@ -2188,7 +2207,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                }
                                let resolved_path = self.resolve_path(&p.path, generics);
                                if let Some(aliased_type) = self.crate_types.type_aliases.get(&resolved_path) {
-                                       return self.write_conversion_new_var_intern(w, ident, var, aliased_type, None, is_ref, ptr_for_ref, to_c, path_lookup, container_lookup, var_prefix, var_suffix);
+                                       return self.write_conversion_new_var_intern(w, ident, var, aliased_type, None, is_ref, ptr_for_ref, to_c, from_ownable_ref, path_lookup, container_lookup, var_prefix, var_suffix);
                                }
                                if self.is_known_container(&resolved_path, is_ref) || self.is_path_transparent_container(&p.path, generics, is_ref) {
                                        if let syn::PathArguments::AngleBracketed(args) = &p.path.segments.iter().next().unwrap().arguments {
@@ -2225,7 +2244,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                true
                                        } else { false }
                                } else if let syn::Type::Reference(ty) = &*s.elem {
-                                       let tyref = [&*ty.elem];
+                                       let tyref = if from_ownable_ref || !to_c { [&*ty.elem] } else { [&*s.elem] };
                                        is_ref = true;
                                        convert_container!("Slice", 1, || tyref.iter().map(|t| generics.resolve_type(*t)));
                                        unimplemented!("convert_container should return true as container_lookup should succeed for slices");
@@ -2266,7 +2285,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                        let v_name = format!("orig_{}_{}", ident, idx);
                                                        let tuple_elem_ident = format_ident!("{}", &v_name);
                                                        if self.write_conversion_new_var_intern(w, &tuple_elem_ident, &v_name, elem, generics,
-                                                                       false, ptr_for_ref, to_c,
+                                                                       false, ptr_for_ref, to_c, from_ownable_ref,
                                                                        path_lookup, container_lookup, var_prefix, var_suffix) {
                                                                write!(w, " ").unwrap();
                                                                // Opaque types with inner pointers shouldn't ever create new stack
@@ -2316,8 +2335,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                }
        }
 
-       pub fn write_to_c_conversion_new_var_inner<W: std::io::Write>(&self, w: &mut W, ident: &syn::Ident, var_access: &str, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool) -> bool {
-               self.write_conversion_new_var_intern(w, ident, var_access, t, generics, false, ptr_for_ref, true,
+       pub fn write_to_c_conversion_new_var_inner<W: std::io::Write>(&self, w: &mut W, ident: &syn::Ident, var_access: &str, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool, from_ownable_ref: bool) -> bool {
+               self.write_conversion_new_var_intern(w, ident, var_access, t, generics, false, ptr_for_ref, true, from_ownable_ref,
                        &|a, b| self.to_c_conversion_new_var_from_path(a, b),
                        &|a, b, c, d, e| self.to_c_conversion_container_new_var(generics, a, b, c, d, e),
                        // We force ptr_for_ref here since we can't generate a ref on one line and use it later
@@ -2325,10 +2344,15 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        &|a, b, c, d, e, f| self.write_to_c_conversion_inline_suffix_inner(a, b, c, d, e, f))
        }
        pub fn write_to_c_conversion_new_var<W: std::io::Write>(&self, w: &mut W, ident: &syn::Ident, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool) -> bool {
-               self.write_to_c_conversion_new_var_inner(w, ident, &format!("{}", ident), t, generics, ptr_for_ref)
+               self.write_to_c_conversion_new_var_inner(w, ident, &format!("{}", ident), t, generics, ptr_for_ref, false)
+       }
+       /// Prints new-var conversion for an "ownable_ref" type, ie prints conversion for
+       /// `create_ownable_reference(t)`, not `t` itself.
+       pub fn write_to_c_conversion_from_ownable_ref_new_var<W: std::io::Write>(&self, w: &mut W, ident: &syn::Ident, t: &syn::Type, generics: Option<&GenericTypes>) -> bool {
+               self.write_to_c_conversion_new_var_inner(w, ident, &format!("{}", ident), t, generics, true, true)
        }
        pub fn write_from_c_conversion_new_var<W: std::io::Write>(&self, w: &mut W, ident: &syn::Ident, t: &syn::Type, generics: Option<&GenericTypes>) -> bool {
-               self.write_conversion_new_var_intern(w, ident, &format!("{}", ident), t, generics, false, false, false,
+               self.write_conversion_new_var_intern(w, ident, &format!("{}", ident), t, generics, false, false, false, false,
                        &|a, b| self.from_c_conversion_new_var_from_path(a, b),
                        &|a, b, c, d, e| self.from_c_conversion_container_new_var(generics, a, b, c, d, e),
                        // We force ptr_for_ref here since we can't generate a ref on one line and use it later