1use crate::utils::{
2 add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State,
3};
4use proc_macro2::{Span, TokenStream};
5use quote::quote;
6use syn::{parse::Result, DeriveInput, Ident};
7
8pub 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