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); } } } |