derive_more/
as_mut.rs

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}