From b20a8ecbb5a435885aa40859f22290929a929a5a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 28 Sep 2023 00:36:43 +0000 Subject: [PATCH] Handle `Deref` bounds as `Self::Type`'s trait bound --- c-bindings-gen/src/types.rs | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 4328e9c..b08c6bc 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -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 { 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. -- 2.39.5