diff options
| author | Martin Fischer <martin@push-f.com> | 2021-11-19 09:50:34 +0100 | 
|---|---|---|
| committer | Martin Fischer <martin@push-f.com> | 2021-11-19 09:51:58 +0100 | 
| commit | eb686879fdd7cde5d09837c202ebd25c9c9889a6 (patch) | |
| tree | ec5388cd7e86513ed01dd5a89527fc44c4576777 /src | |
| parent | 8e99d7bd6ebf9d1981667799f43cf45f682e1fff (diff) | |
refactor: forward type param transforms as HashMap
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 56 | ||||
| -rw-r--r-- | src/parse_trait_sig.rs | 23 | ||||
| -rw-r--r-- | src/transform.rs | 15 | 
3 files changed, 46 insertions, 48 deletions
| @@ -78,7 +78,7 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {                      )                  }                  Ok((ident, type_)) => { -                    assoc_type_conversions.0.insert(ident, type_); +                    assoc_type_conversions.0.insert(ident.clone(), type_);                  }              }          } @@ -181,32 +181,40 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {          let fun_name = &new_method.sig.ident; -        let args = new_method -            .sig -            .inputs -            .iter() -            .enumerate() -            .map(|(idx, arg)| match arg { -                syn::FnArg::Receiver(_) => quote! {self}, -                syn::FnArg::Typed(pat_type) => match pat_type.pat.as_ref() { -                    syn::Pat::Ident(ident) => match &parsed_method.inputs[idx] { -                        None => ident.ident.to_token_stream(), -                        Some(transforms) => { -                            let args = (0..transforms.len()).map(|i| format_ident!("a{}", i)); -                            let mut calls: Vec<_> = -                                args.clone().map(|i| i.into_token_stream()).collect(); -                            for i in 0..calls.len() { -                                transforms[i].append_conversion(&mut calls[i]); +        let args = new_method.sig.inputs.iter().map(|arg| match arg { +            syn::FnArg::Receiver(_) => quote! {self}, +            syn::FnArg::Typed(pat_type) => match pat_type.pat.as_ref() { +                syn::Pat::Ident(ident) => { +                    // FUTURE: use try block +                    if let Type::Path(path) = &*pat_type.ty { +                        if let Some(type_ident) = path.path.get_ident() { +                            if let Some(transforms) = +                                parsed_method.type_param_transforms.get(type_ident) +                            { +                                let args = (0..transforms.len()).map(|i| format_ident!("a{}", i)); +                                let mut calls: Vec<_> = +                                    args.clone().map(|i| i.into_token_stream()).collect(); +                                for i in 0..calls.len() { +                                    transforms[i].append_conversion(&mut calls[i]); +                                } +                                let move_opt = new_method.sig.asyncness.map(|_| quote! {move}); +                                quote!(#move_opt |#(#args),*| #ident(#(#calls),*)) +                            } else { +                                ident.ident.to_token_stream()                              } -                            let move_opt = new_method.sig.asyncness.map(|_| quote! {move}); -                            quote!(#move_opt |#(#args),*| #ident(#(#calls),*)) +                        } else { +                            ident.ident.to_token_stream()                          } -                    }, -                    _other => { -                        panic!("unexpected"); +                    } else { +                        ident.ident.to_token_stream()                      } -                }, -            }); +                } + +                _other => { +                    panic!("unexpected"); +                } +            }, +        });          // in order for a trait to be object-safe its methods may not have          // generics so we convert method generics into trait generics diff --git a/src/parse_trait_sig.rs b/src/parse_trait_sig.rs index 0078c93..5b1f91a 100644 --- a/src/parse_trait_sig.rs +++ b/src/parse_trait_sig.rs @@ -1,8 +1,10 @@ +use std::collections::HashMap; +  use proc_macro2::Span;  use syn::{      spanned::Spanned, FnArg, PredicateType, Receiver, ReturnType, Type, TypePath, WherePredicate,  }; -use syn::{Signature, TypeImplTrait}; +use syn::{Ident, Signature, TypeImplTrait};  use crate::syn_utils::{find_in_type, trait_bounds, TypeMatcher};  use crate::transform::{dynamize_function_bounds, AssocTypeConversions, TransformError}; @@ -40,7 +42,7 @@ impl TypeMatcher<TypeImplTrait> for ImplTraitMatcher {  pub struct SignatureChanges {      pub return_type: TypeTransform, -    pub inputs: Vec<Option<Vec<TypeTransform>>>, +    pub type_param_transforms: HashMap<Ident, Vec<TypeTransform>>,  }  pub fn parse_trait_signature( @@ -65,19 +67,6 @@ pub fn parse_trait_signature(      let type_param_transforms =          dynamize_function_bounds(&mut signature.generics, assoc_type_conversions)?; -    let mut input_transforms = Vec::new(); - -    for input in &signature.inputs { -        if let FnArg::Typed(pattype) = input { -            if let Type::Path(path) = &*pattype.ty { -                if let Some(ident) = path.path.get_ident() { -                    input_transforms.push(type_param_transforms.get(ident).map(|x| (*x).clone())); -                    continue; -                } -            } -        } -        input_transforms.push(None); -    }      let return_type = match &mut signature.output {          ReturnType::Type(_, og_type) => match assoc_type_conversions.parse_type_path(og_type) { @@ -93,7 +82,7 @@ pub fn parse_trait_signature(      };      Ok(SignatureChanges {          return_type, -        inputs: input_transforms, +        type_param_transforms,      })  } @@ -184,7 +173,7 @@ mod tests {          let mut assoc_type_map = AssocTypeConversions::default();          let ident = format_ident!("A");          let dest = Type::Verbatim(quote! {Example}); -        assoc_type_map.0.insert(&ident, &dest); +        assoc_type_map.0.insert(ident, &dest);          assert!(matches!(              parse_trait_signature(&mut type1.sig, &assoc_type_map), diff --git a/src/transform.rs b/src/transform.rs index 4fc22f5..ec2f3a6 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -12,7 +12,7 @@ use crate::{  };  #[derive(Default)] -pub struct AssocTypeConversions<'a>(pub HashMap<&'a Ident, &'a Type>); +pub struct AssocTypeConversions<'a>(pub HashMap<Ident, &'a Type>);  pub enum TransformError {      UnconvertibleAssocType(Span), @@ -36,7 +36,7 @@ impl AssocTypeConversions<'_> {                  let ident = &path.segments.last().unwrap().ident;                  *type_ = (*self                      .0 -                    .get(&ident) +                    .get(ident)                      .ok_or_else(|| TransformError::UnconvertibleAssocType(ident.span()))?)                  .clone();                  return Ok(TypeTransform::Into); @@ -100,10 +100,10 @@ impl AssocTypeConversions<'_> {      }  } -pub fn dynamize_function_bounds<'a>( -    generics: &'a mut Generics, -    assoc_type_conversions: &AssocTypeConversions<'a>, -) -> Result<HashMap<&'a Ident, Vec<TypeTransform>>, (Span, MethodParseError)> { +pub fn dynamize_function_bounds( +    generics: &mut Generics, +    assoc_type_conversions: &AssocTypeConversions, +) -> Result<HashMap<Ident, Vec<TypeTransform>>, (Span, MethodParseError)> {      let mut type_param_transforms = HashMap::new();      for generic_param in &mut generics.params { @@ -139,7 +139,8 @@ pub fn dynamize_function_bounds<'a>(                                      }                                  }                                  if transforms.iter().any(|t| !matches!(t, TypeTransform::NoOp)) { -                                    type_param_transforms.insert(&type_param.ident, transforms); +                                    type_param_transforms +                                        .insert(type_param.ident.clone(), transforms);                                  }                              }                          } | 
