From 56001280fb0fa4591492dc3766b8509dd51826e6 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 13 Apr 2021 19:27:22 -0400 Subject: [PATCH] Handle concrete Deref bounds in generic args --- c-bindings-gen/src/types.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 26a0885..bd0c9c5 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -176,7 +176,7 @@ pub struct GenericTypes<'a, 'b> { self_ty: Option<(String, &'a syn::Path)>, parent: Option<&'b GenericTypes<'b, 'b>>, typed_generics: HashMap<&'a syn::Ident, (String, Option<&'a syn::Path>)>, - default_generics: HashMap<&'a syn::Ident, (&'a syn::Type, syn::Type)>, + default_generics: HashMap<&'a syn::Ident, (syn::Type, syn::Type)>, } impl<'a, 'p: 'a> GenericTypes<'a, 'p> { pub fn new(self_ty: Option<(String, &'a syn::Path)>) -> Self { @@ -197,7 +197,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { match generic { syn::GenericParam::Type(type_param) => { let mut non_lifetimes_processed = false; - for bound in type_param.bounds.iter() { + 'bound_loop: for bound in type_param.bounds.iter() { if let syn::TypeParamBound::Trait(trait_bound) = bound { if let Some(ident) = single_ident_generic_path_to_ident(&trait_bound.path) { match &format!("{}", ident) as &str { "Send" => continue, "Sync" => continue, _ => {} } @@ -213,6 +213,26 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { let new_ident = if path != "std::ops::Deref" && path != "core::ops::Deref" { path = "crate::".to_string() + &path; Some(&trait_bound.path) + } else if trait_bound.path.segments.len() == 1 { + // If we're templated on Deref, store + // the reference type in `default_generics` which handles full + // types and not just paths. + if let syn::PathArguments::AngleBracketed(ref args) = + trait_bound.path.segments[0].arguments { + for subargument in args.args.iter() { + match subargument { + syn::GenericArgument::Lifetime(_) => {}, + syn::GenericArgument::Binding(ref b) => { + if &format!("{}", b.ident) != "Target" { return false; } + let default = &b.ty; + self.default_generics.insert(&type_param.ident, (parse_quote!(&#default), parse_quote!(&#default))); + break 'bound_loop; + }, + _ => unimplemented!(), + } + } + None + } else { None } } else { None }; self.typed_generics.insert(&type_param.ident, (path, new_ident)); } else { return false; } @@ -220,7 +240,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { } if let Some(default) = type_param.default.as_ref() { assert!(type_param.bounds.is_empty()); - self.default_generics.insert(&type_param.ident, (default, parse_quote!(&#default))); + self.default_generics.insert(&type_param.ident, (default.clone(), parse_quote!(&#default))); } }, _ => {}, -- 2.30.2