diff options
| -rw-r--r-- | src/lib.rs | 10 | ||||
| -rw-r--r-- | src/trait_sig.rs | 35 | ||||
| -rw-r--r-- | src/transform.rs | 16 | ||||
| -rw-r--r-- | ui-tests/src/bin/attr_convert_unused.rs | 7 | ||||
| -rw-r--r-- | ui-tests/src/bin/attr_convert_unused.stderr | 5 | 
5 files changed, 51 insertions, 22 deletions
| @@ -97,6 +97,7 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {          assoc_type_conversions: HashMap::new(),          collections: method_attrs.collections,          type_conversions: method_attrs.type_conversions, +        used_conversions: Default::default(),      };      for item in &original_trait.items { @@ -127,7 +128,7 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {          if let TraitItem::Method(method) = item {              let mut signature = method.sig.clone(); -            match convert_trait_signature(&mut signature, &type_converter) { +            match convert_trait_signature(&mut signature, &mut type_converter) {                  Ok(parsed_method) => objectifiable_methods.push((signature, parsed_method)),                  Err((span, err)) => match err {                      MethodError::NonDispatchableMethod => continue, @@ -181,6 +182,13 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {          }      } +    for ty in type_converter.type_conversions.keys() { +        if !type_converter.used_conversions.contains(ty) { +            // FUTURE: relax to warning once proc_macro::Diagnostic is stable +            return abort!(ty.span(), "unused conversion"); +        } +    } +      let mut method_impls: Vec<ImplItemMethod> = Vec::new();      let mut dyn_trait = ItemTrait { diff --git a/src/trait_sig.rs b/src/trait_sig.rs index a1be44f..ce6f318 100644 --- a/src/trait_sig.rs +++ b/src/trait_sig.rs @@ -57,7 +57,7 @@ pub struct SignatureChanges {  pub fn convert_trait_signature(      signature: &mut Signature, -    type_converter: &TypeConverter, +    type_converter: &mut TypeConverter,  ) -> Result<SignatureChanges, (Span, MethodError)> {      if is_non_dispatchable(signature) {          return Err((signature.span(), MethodError::NonDispatchableMethod)); @@ -144,7 +144,7 @@ fn bounds_self_and_has_bound_sized(predicate: &WherePredicate) -> bool {  #[cfg(test)]  mod tests { -    use std::collections::HashMap; +    use std::collections::{HashMap, HashSet};      use quote::{format_ident, quote};      use syn::{TraitItemMethod, Type}; @@ -161,6 +161,7 @@ mod tests {              collections: HashMap::new(),              trait_ident: format_ident!("test"),              type_conversions: HashMap::new(), +            used_conversions: HashSet::new(),          }      } @@ -172,7 +173,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Ok(SignatureChanges {                  return_type: TypeTransform::NoOp,                  .. @@ -194,7 +195,7 @@ mod tests {          type_converter.assoc_type_conversions.insert(ident, dest);          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &type_converter), +            convert_trait_signature(&mut type1.sig, &mut type_converter),              Ok(SignatureChanges {                  return_type: TypeTransform::Into,                  .. @@ -210,7 +211,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((                  _,                  MethodError::Transform(TransformError::AssocTypeWithoutDestType) @@ -226,7 +227,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -239,7 +240,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -252,7 +253,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -265,7 +266,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -278,7 +279,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -291,7 +292,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -304,7 +305,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -317,7 +318,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -330,7 +331,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::AssocTypeInInputs))          ));      } @@ -343,7 +344,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::AssocTypeInInputs))          ));      } @@ -356,7 +357,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::ImplTraitInInputs))          ));      } @@ -369,7 +370,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &test_converter()), +            convert_trait_signature(&mut type1.sig, &mut test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } diff --git a/src/transform.rs b/src/transform.rs index ae345c8..c56bec1 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, rc::Rc}; +use std::{ +    collections::{HashMap, HashSet}, +    rc::Rc, +};  use proc_macro2::Span;  use quote::quote; @@ -20,6 +23,7 @@ pub struct TypeConverter {      pub collections: HashMap<Ident, usize>,      pub trait_ident: Ident,      pub type_conversions: HashMap<Type, Rc<Convert>>, +    pub used_conversions: HashSet<Type>,  }  #[derive(Debug)] @@ -60,8 +64,12 @@ impl TypeConverter {          None      } -    pub fn convert_type(&self, type_: &mut Type) -> Result<TypeTransform, (Span, TransformError)> { +    pub fn convert_type( +        &mut self, +        type_: &mut Type, +    ) -> Result<TypeTransform, (Span, TransformError)> {          if let Some(conv) = self.type_conversions.get(type_) { +            self.used_conversions.insert(conv.original_type.clone());              *type_ = conv.dest_type.clone();              return Ok(TypeTransform::Verbatim(conv.clone()));          } @@ -223,7 +231,7 @@ impl TypeConverter {  pub fn dynamize_function_bounds(      generics: &mut Generics, -    type_converter: &TypeConverter, +    type_converter: &mut TypeConverter,  ) -> Result<HashMap<Ident, Vec<TypeTransform>>, (Span, MethodError)> {      let mut type_param_transforms = HashMap::new(); @@ -285,7 +293,7 @@ pub fn dynamize_function_bounds(  fn dynamize_trait_bound(      bound: &mut TraitBound, -    type_converter: &TypeConverter, +    type_converter: &mut TypeConverter,      type_ident: &Ident,      type_param_transforms: &mut HashMap<Ident, Vec<TypeTransform>>,  ) -> Result<(), (Span, MethodError)> { diff --git a/ui-tests/src/bin/attr_convert_unused.rs b/ui-tests/src/bin/attr_convert_unused.rs new file mode 100644 index 0000000..b7ee474 --- /dev/null +++ b/ui-tests/src/bin/attr_convert_unused.rs @@ -0,0 +1,7 @@ +#[dynamize::dynamize] +#[convert = |x: Foo| -> Bar {x.baz()}] +trait Trait { +    fn test(&self); +} + +fn main() {} diff --git a/ui-tests/src/bin/attr_convert_unused.stderr b/ui-tests/src/bin/attr_convert_unused.stderr new file mode 100644 index 0000000..e715236 --- /dev/null +++ b/ui-tests/src/bin/attr_convert_unused.stderr @@ -0,0 +1,5 @@ +error: unused conversion + --> src/bin/attr_convert_unused.rs:2:17 +  | +2 | #[convert = |x: Foo| -> Bar {x.baz()}] +  |                 ^^^ | 
