diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 25 |
1 files changed, 23 insertions, 2 deletions
@@ -1,5 +1,7 @@ #![doc = include_str!("../README.md")] +use std::collections::HashMap; + use proc_macro::TokenStream; use proc_macro2::Group; use quote::format_ident; @@ -8,6 +10,7 @@ use quote::quote_spanned; use quote::ToTokens; use syn::parse_macro_input; use syn::punctuated::Punctuated; +use syn::spanned::Spanned; use syn::token::Brace; use syn::token::Gt; use syn::token::Lt; @@ -171,6 +174,14 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream { items: Vec::new(), }; + let mut generic_map = HashMap::new(); + + for generic in &dyn_trait.generics.params { + if let GenericParam::Type(type_param) = generic { + generic_map.insert(type_param.ident.clone(), type_param.bounds.clone()); + } + } + for (signature, parsed_method) in objectifiable_methods { let mut new_method = TraitItemMethod { attrs: Vec::new(), @@ -235,8 +246,18 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream { // FUTURE: use Vec::drain_filter once it's stable let mut i = 0; while i < params.len() { - if matches!(params[i], GenericParam::Type(_)) { - dyn_trait.generics.params.push(params.remove(i)); + if let GenericParam::Type(type_param) = ¶ms[i] { + if let Some(bounds) = generic_map.get(&type_param.ident) { + if *bounds == type_param.bounds { + params.remove(i); + continue; + } else { + return abort!(type_param.span(), "dynamize failure: there exists a same-named method generic with different bounds"); + } + } else { + generic_map.insert(type_param.ident.clone(), type_param.bounds.clone()); + dyn_trait.generics.params.push(params.remove(i)); + } } else { i += 1; } |