diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/parse_trait_sig.rs | 1 | ||||
| -rw-r--r-- | src/syn_utils.rs | 2 | ||||
| -rw-r--r-- | src/transform.rs | 46 | 
4 files changed, 49 insertions, 4 deletions
| @@ -390,6 +390,10 @@ impl TypeTransform {                  let inner = opt.convert(quote!(x));                  quote! {#arg.map(|x| #inner)}              } +            TypeTransform::Iterator(inner) => { +                let inner = inner.convert(quote!(x)); +                quote! {Box::new(#arg.map(|x| #inner))} +            }              TypeTransform::Result(ok, err) => {                  let map_ok = !matches!(ok.as_ref(), TypeTransform::NoOp);                  let map_err = !matches!(err.as_ref(), TypeTransform::NoOp); diff --git a/src/parse_trait_sig.rs b/src/parse_trait_sig.rs index 82b8ee9..cf2d7da 100644 --- a/src/parse_trait_sig.rs +++ b/src/parse_trait_sig.rs @@ -17,6 +17,7 @@ pub enum TypeTransform {      Into,      Box(BoxType),      Map(Box<TypeTransform>), +    Iterator(Box<TypeTransform>),      Result(Box<TypeTransform>, Box<TypeTransform>),  } diff --git a/src/syn_utils.rs b/src/syn_utils.rs index 43c4d94..ea4b5ea 100644 --- a/src/syn_utils.rs +++ b/src/syn_utils.rs @@ -128,6 +128,8 @@ fn types_in_path(p: &Path) -> impl Iterator<Item = &Type> {          PathArguments::AngleBracketed(ang) => {              IterEnum::Left(ang.args.iter().flat_map(|a| match a {                  GenericArgument::Type(t) => Some(t), +                GenericArgument::Binding(b) => Some(&b.ty), +                // TODO: handle GenericArgument::Constraint                  _other => None,              }))          } diff --git a/src/transform.rs b/src/transform.rs index b13b7cf..fff9c6c 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -1,9 +1,10 @@  use std::collections::HashMap;  use proc_macro2::Span; +use quote::quote;  use syn::{      spanned::Spanned, GenericArgument, Generics, Ident, PathArguments, TraitBound, Type, -    TypeParamBound, TypePath, WherePredicate, +    TypeParamBound, TypePath, TypeReference, TypeTraitObject, WherePredicate,  };  use crate::{ @@ -28,12 +29,49 @@ impl AssocTypeConversions<'_> {              None => return Ok(TypeTransform::NoOp),          }; +        if let Type::Reference(TypeReference { +            lifetime: None, +            mutability: Some(_), +            elem, +            .. +        }) = type_ +        { +            if let Type::TraitObject(TypeTraitObject { +                dyn_token: Some(_), +                bounds, +            }) = elem.as_mut() +            { +                if bounds.len() == 1 { +                    if let TypeParamBound::Trait(bound) = bounds.first_mut().unwrap() { +                        if bound.path.segments.len() == 1 { +                            let first = bound.path.segments.first_mut().unwrap(); +                            if first.ident == "Iterator" { +                                if let PathArguments::AngleBracketed(args) = &mut first.arguments { +                                    if args.args.len() == 1 { +                                        if let GenericArgument::Binding(binding) = +                                            args.args.first_mut().unwrap() +                                        { +                                            if binding.ident == "Item" +                                                && iter_type(&binding.ty).any(match_assoc_type) +                                            { +                                                let inner = +                                                    self.parse_type_path(&mut binding.ty)?; +                                                *type_ = Type::Verbatim(quote! {Box<#elem + '_>}); +                                                return Ok(TypeTransform::Iterator(inner.into())); +                                            } +                                        } +                                    } +                                } +                            } +                        } +                    } +                } +            } +        } +          if let Type::Path(TypePath { path, qself: None }) = type_ {              let ident = &path.segments.first().unwrap().ident; -            // TODO: support &mut dyn Iterator<Item = Self::A> -            // conversion to  Box<dyn Iterator<Item = Whatever>> via .map(Into::into) -              if ident == "Self" && path.segments.len() == 2 {                  let ident = &path.segments.last().unwrap().ident;                  let dest_type = self | 
