aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-11-19 09:50:34 +0100
committerMartin Fischer <martin@push-f.com>2021-11-19 09:51:58 +0100
commiteb686879fdd7cde5d09837c202ebd25c9c9889a6 (patch)
treeec5388cd7e86513ed01dd5a89527fc44c4576777
parent8e99d7bd6ebf9d1981667799f43cf45f682e1fff (diff)
refactor: forward type param transforms as HashMap
-rw-r--r--src/lib.rs56
-rw-r--r--src/parse_trait_sig.rs23
-rw-r--r--src/transform.rs15
3 files changed, 46 insertions, 48 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 7f4e040..6e88136 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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);
}
}
}