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