aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 6e88136..5385181 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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) = &params[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;
}