diff options
author | Martin Fischer <martin@push-f.com> | 2021-11-26 10:27:50 +0100 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2021-11-26 11:45:53 +0100 |
commit | d37cf6a72e633afb10ec78bdbeec6631d601adfe (patch) | |
tree | 1db3a4b735382c65c0feed07a3328cdd059c4bd5 | |
parent | 7489a3c2246e7ea2483446dd2ed3fdbfaf462c1a (diff) |
return error for unused #[convert]s
-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()}] + | ^^^ |