diff options
Diffstat (limited to 'third_party/rust/derive_more-impl/src/into_iterator.rs')
-rw-r--r-- | third_party/rust/derive_more-impl/src/into_iterator.rs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/third_party/rust/derive_more-impl/src/into_iterator.rs b/third_party/rust/derive_more-impl/src/into_iterator.rs new file mode 100644 index 0000000000..f10dbf7a0b --- /dev/null +++ b/third_party/rust/derive_more-impl/src/into_iterator.rs @@ -0,0 +1,59 @@ +use crate::utils::{ + add_extra_generic_param, add_extra_ty_param_bound_ref, SingleFieldData, State, +}; +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use syn::{parse::Result, DeriveInput}; + +/// Provides the hook to expand `#[derive(IntoIterator)]` into an implementation of `IntoIterator` +pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> { + let state = + State::with_field_ignore_and_refs(input, trait_name, "into_iterator".into())?; + let SingleFieldData { + input_type, + info, + field_type, + member, + trait_path, + .. + } = state.assert_single_enabled_field(); + + let mut tokens = TokenStream::new(); + + for ref_type in info.ref_types() { + let reference = ref_type.reference(); + let lifetime = ref_type.lifetime(); + let reference_with_lifetime = ref_type.reference_with_lifetime(); + + let generics_impl; + let generics = + add_extra_ty_param_bound_ref(&input.generics, trait_path, ref_type); + let (_, ty_generics, where_clause) = generics.split_for_impl(); + let (impl_generics, _, _) = if ref_type.is_ref() { + generics_impl = add_extra_generic_param(&generics, lifetime.clone()); + generics_impl.split_for_impl() + } else { + generics.split_for_impl() + }; + // let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let casted_trait = "e! { + <#reference_with_lifetime #field_type as #trait_path> + }; + let into_iterator = quote! { + #[automatically_derived] + impl #impl_generics #trait_path for #reference_with_lifetime #input_type #ty_generics + #where_clause + { + type Item = #casted_trait::Item; + type IntoIter = #casted_trait::IntoIter; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + #casted_trait::into_iter(#reference #member) + } + } + }; + into_iterator.to_tokens(&mut tokens); + } + Ok(tokens) +} |