Handle `Deref<Self::Type>` bounds as `Self::Type`'s trait bound
authorMatt Corallo <git@bluematt.me>
Thu, 28 Sep 2023 00:36:43 +0000 (00:36 +0000)
committerMatt Corallo <git@bluematt.me>
Wed, 4 Oct 2023 20:02:23 +0000 (20:02 +0000)
c-bindings-gen/src/types.rs

index 4328e9c5e262578b5d23c29c2ffc51aacaec019e..b08c6bc9d30bbc3a938033d5135d03084bab7076 100644 (file)
@@ -351,6 +351,21 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> {
                                                                        if path != "std::ops::Deref" && path != "core::ops::Deref" &&
                                                                        path != "std::ops::DerefMut" && path != "core::ops::DerefMut" {
                                                                                self.typed_generics.insert(&t.ident, path);
+                                                                       } else {
+                                                                               let last_seg_args = &tr.path.segments.last().unwrap().arguments;
+                                                                               if let syn::PathArguments::AngleBracketed(args) = last_seg_args {
+                                                                                       assert_eq!(args.args.len(), 1);
+                                                                                       if let syn::GenericArgument::Binding(binding) = &args.args[0] {
+                                                                                               assert_eq!(format!("{}", binding.ident), "Target");
+                                                                                               if let syn::Type::Path(p) = &binding.ty {
+                                                                                                       // Note that we are assuming the order of type
+                                                                                                       // declarations here, but that should be easy
+                                                                                                       // to handle.
+                                                                                                       let real_path = self.maybe_resolve_path(&p.path).unwrap();
+                                                                                                       self.typed_generics.insert(&t.ident, real_path.clone());
+                                                                                               } else { unimplemented!(); }
+                                                                                       } else { unimplemented!(); }
+                                                                               } else { unimplemented!(); }
                                                                        }
                                                                } else { unimplemented!(); }
                                                                for bound in bounds_iter {
@@ -670,6 +685,33 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr
 
        pub fn maybe_resolve_path(&self, p: &syn::Path, generics: Option<&GenericTypes>) -> Option<String> {
                self.maybe_resolve_imported_path(p, generics).map(|mut path| {
+                       if path == "core::ops::Deref" || path == "core::ops::DerefMut" {
+                               let last_seg = p.segments.last().unwrap();
+                               if let syn::PathArguments::AngleBracketed(args) = &last_seg.arguments {
+                                       assert_eq!(args.args.len(), 1);
+                                       if let syn::GenericArgument::Binding(binding) = &args.args[0] {
+                                               if let syn::Type::Path(p) = &binding.ty {
+                                                       if let Some(inner_ty) = self.maybe_resolve_path(&p.path, generics) {
+                                                               let mut module_riter = inner_ty.rsplitn(2, "::");
+                                                               let ty_ident = module_riter.next().unwrap();
+                                                               let module_name = module_riter.next().unwrap();
+                                                               let module = self.library.modules.get(module_name).unwrap();
+                                                               for item in module.items.iter() {
+                                                                       match item {
+                                                                               syn::Item::Trait(t) => {
+                                                                                       if t.ident == ty_ident {
+                                                                                               path = inner_ty;
+                                                                                               break;
+                                                                                       }
+                                                                               },
+                                                                               _ => {}
+                                                                       }
+                                                               }
+                                                       }
+                                               } else { unimplemented!(); }
+                                       } else { unimplemented!(); }
+                               }
+                       }
                        loop {
                                // Now that we've resolved the path to the path as-imported, check whether the path
                                // is actually a pub(.*) use statement and map it to the real path.