diff options
author | Martin Fischer <martin@push-f.com> | 2021-11-21 09:37:32 +0100 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2021-11-21 09:39:40 +0100 |
commit | 57641e00d6ed1fd7689c3079abb10f67d5387143 (patch) | |
tree | adb48bb70be52bc6035d93826f7725dd64054b49 /src/transform.rs | |
parent | 34dc166a9bc003bad36c28aeb29b625195d20a74 (diff) |
support -> &mut dyn Iterator<Item = Self::A>
Diffstat (limited to 'src/transform.rs')
-rw-r--r-- | src/transform.rs | 46 |
1 files changed, 42 insertions, 4 deletions
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 |