diff options
| author | Martin Fischer <martin@push-f.com> | 2021-11-25 13:48:26 +0100 | 
|---|---|---|
| committer | Martin Fischer <martin@push-f.com> | 2021-11-25 13:48:46 +0100 | 
| commit | 8046190e8f537407210fb87acbfe96d4084d58da (patch) | |
| tree | 34c093627f5fd75db82cb8fb48402b82ace7d803 | |
| parent | 74a29b912aaa14dbeb7e5c51ae11c61e733ef645 (diff) | |
support Self qualified as same trait
| -rw-r--r-- | src/lib.rs | 7 | ||||
| -rw-r--r-- | src/trait_sig.rs | 40 | ||||
| -rw-r--r-- | src/transform.rs | 27 | ||||
| -rw-r--r-- | tests/tests.rs | 2 | ||||
| -rw-r--r-- | ui-tests/src/bin/qualified_self.stderr | 6 | ||||
| -rw-r--r-- | ui-tests/src/bin/qualified_self_opt.stderr | 6 | 
6 files changed, 57 insertions, 31 deletions
| @@ -85,7 +85,8 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {      let mut type_converter = TypeConverter {          collections: method_attrs.collections, -        ..TypeConverter::default() +        assoc_type_conversions: HashMap::new(), +        trait_ident: original_trait.ident.clone(),      };      for item in &original_trait.items { @@ -158,8 +159,8 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {                      MethodError::Transform(TransformError::QualifiedAssociatedType) => {                          return abort!(span, "dynamize does not support qualified associated types")                      } -                    MethodError::Transform(TransformError::QualifiedSelfAssociatedType) => { -                        return abort!(span, "dynamize does not support associated types of a qualified Self") +                    MethodError::Transform(TransformError::SelfQualifiedAsOtherTrait) => { +                        return abort!(span, "dynamize does not support Self qualified as another trait")                      }                      MethodError::UnconvertedAssocType => {                          return abort!(span, "dynamize does not support associated types here") diff --git a/src/trait_sig.rs b/src/trait_sig.rs index 3fb439f..5d8eddf 100644 --- a/src/trait_sig.rs +++ b/src/trait_sig.rs @@ -140,6 +140,8 @@ fn bounds_self_and_has_bound_sized(predicate: &WherePredicate) -> bool {  #[cfg(test)]  mod tests { +    use std::collections::HashMap; +      use quote::{format_ident, quote};      use syn::{TraitItemMethod, Type}; @@ -149,6 +151,14 @@ mod tests {          transform::{TransformError, TypeConverter},      }; +    fn test_converter() -> TypeConverter<'static> { +        TypeConverter { +            assoc_type_conversions: HashMap::new(), +            collections: HashMap::new(), +            trait_ident: format_ident!("test"), +        } +    } +      #[test]      fn ok_void() {          let mut type1: TraitItemMethod = syn::parse2(quote! { @@ -157,7 +167,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Ok(SignatureChanges {                  return_type: TypeTransform::NoOp,                  .. @@ -172,7 +182,7 @@ mod tests {          })          .unwrap(); -        let mut type_converter = TypeConverter::default(); +        let mut type_converter = test_converter();          let ident = format_ident!("A");          let dest_inner = Type::Verbatim(quote! {Example});          let dest = DestType::Into(&dest_inner); @@ -195,7 +205,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((                  _,                  MethodError::Transform(TransformError::AssocTypeWithoutDestType) @@ -211,7 +221,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -224,7 +234,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -237,7 +247,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -250,7 +260,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::NonDispatchableMethod))          ));      } @@ -263,7 +273,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -276,7 +286,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -289,7 +299,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -302,7 +312,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } @@ -315,7 +325,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::AssocTypeInInputs))          ));      } @@ -328,7 +338,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::AssocTypeInInputs))          ));      } @@ -341,7 +351,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::ImplTraitInInputs))          ));      } @@ -354,7 +364,7 @@ mod tests {          .unwrap();          assert!(matches!( -            convert_trait_signature(&mut type1.sig, &Default::default()), +            convert_trait_signature(&mut type1.sig, &test_converter()),              Err((_, MethodError::Transform(TransformError::UnsupportedType)))          ));      } diff --git a/src/transform.rs b/src/transform.rs index eed48c4..75138c9 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -14,10 +14,10 @@ use crate::{      trait_sig::{MethodError, TypeTransform},  }; -#[derive(Default)]  pub struct TypeConverter<'a> {      pub assoc_type_conversions: HashMap<Ident, DestType<'a>>,      pub collections: HashMap<Ident, usize>, +    pub trait_ident: Ident,  }  #[derive(Debug)] @@ -27,7 +27,7 @@ pub enum TransformError {      ExpectedAtLeastNTypes(usize),      AssocTypeAfterFirstNTypes(usize, Ident),      QualifiedAssociatedType, -    QualifiedSelfAssociatedType, +    SelfQualifiedAsOtherTrait,  }  impl TypeConverter<'_> { @@ -115,7 +115,8 @@ impl TypeConverter<'_> {          }          if let Type::Path(TypePath { -            qself: Some(qself), .. +            path, +            qself: Some(qself),          }) = type_          {              if let Type::Path(self_path) = qself.ty.as_ref() { @@ -123,10 +124,22 @@ impl TypeConverter<'_> {                      if !self_path.path.is_ident("Self") {                          return Err((self_path.span(), TransformError::QualifiedAssociatedType));                      } -                    return Err(( -                        self_path.span(), -                        TransformError::QualifiedSelfAssociatedType, -                    )); + +                    if qself.position == 1 +                        && path.segments.len() == 2 +                        && path.segments[0].arguments.is_empty() +                        && path.segments[0].ident == self.trait_ident +                    { +                        let ident = &path.segments[1].ident; +                        let dest_type = +                            self.assoc_type_conversions.get(ident).ok_or_else(|| { +                                (ident.span(), TransformError::AssocTypeWithoutDestType) +                            })?; +                        *type_ = dest_type.get_dest(); +                        return Ok(dest_type.type_transformation()); +                    } + +                    return Err((path.span(), TransformError::SelfQualifiedAsOtherTrait));                  }              }          } else if let Type::Path(TypePath { path, qself: None }) = type_ { diff --git a/tests/tests.rs b/tests/tests.rs index e30b0ef..e3df519 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -35,6 +35,8 @@ fn it_works() {          #[allow(clippy::type_complexity)]          fn test10(&self) -> (Self::A, (Self::A, Self::B), Self::B); +        fn test11(&self) -> <Self as MyTrait>::A; +          // fn test9(&self) -> &dyn Iterator<Item = Self::A>;          fn mut1(&mut self) -> Self::A; diff --git a/ui-tests/src/bin/qualified_self.stderr b/ui-tests/src/bin/qualified_self.stderr index 1b5f9f9..d8c3a37 100644 --- a/ui-tests/src/bin/qualified_self.stderr +++ b/ui-tests/src/bin/qualified_self.stderr @@ -1,5 +1,5 @@ -error: dynamize does not support associated types of a qualified Self - --> src/bin/qualified_self.rs:7:24 +error: dynamize does not support Self qualified as another trait + --> src/bin/qualified_self.rs:7:32    |  7 |     fn test(&self) -> <Self as Foo>::X; -  |                        ^^^^ +  |                                ^^^ diff --git a/ui-tests/src/bin/qualified_self_opt.stderr b/ui-tests/src/bin/qualified_self_opt.stderr index e032be5..dd99406 100644 --- a/ui-tests/src/bin/qualified_self_opt.stderr +++ b/ui-tests/src/bin/qualified_self_opt.stderr @@ -1,5 +1,5 @@ -error: dynamize does not support associated types of a qualified Self - --> src/bin/qualified_self_opt.rs:7:31 +error: dynamize does not support Self qualified as another trait + --> src/bin/qualified_self_opt.rs:7:39    |  7 |     fn test(&self) -> Option<<Self as Foo>::X>; -  |                               ^^^^ +  |                                       ^^^ | 
