1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use crate::utils::{ add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State, }; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{parse::Result, DeriveInput, Ident}; pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> { let as_ref_type = &Ident::new("__AsRefT", Span::call_site()); let state = State::with_type_bound( input, trait_name, quote!(::core::convert), String::from("as_ref"), AttrParams::ignore_and_forward(), false, )?; let MultiFieldData { fields, input_type, members, infos, trait_path, impl_generics, ty_generics, where_clause, .. } = state.enabled_fields_data(); let sub_items: Vec<_> = infos .iter() .zip(members.iter()) .zip(fields) .map(|((info, member), field)| { let field_type = &field.ty; if info.forward { let trait_path = quote!(#trait_path<#as_ref_type>); let type_where_clauses = quote! { where #field_type: #trait_path }; let new_generics = add_where_clauses_for_new_ident( &input.generics, &[field], as_ref_type, type_where_clauses, false, ); let (impl_generics, _, where_clause) = new_generics.split_for_impl(); let casted_trait = quote!(<#field_type as #trait_path>); ( quote!(#casted_trait::as_ref(&#member)), quote!(#impl_generics), quote!(#where_clause), quote!(#trait_path), quote!(#as_ref_type), ) } else { ( quote!(&#member), quote!(#impl_generics), quote!(#where_clause), quote!(#trait_path<#field_type>), quote!(#field_type), ) } }) .collect(); let bodies = sub_items.iter().map(|i| &i.0); let impl_generics = sub_items.iter().map(|i| &i.1); let where_clauses = sub_items.iter().map(|i| &i.2); let trait_paths = sub_items.iter().map(|i| &i.3); let return_types = sub_items.iter().map(|i| &i.4); Ok(quote! {#( impl#impl_generics #trait_paths for #input_type#ty_generics #where_clauses { #[inline] fn as_ref(&self) -> &#return_types { #bodies } } )*}) }