1use crate::utils::{add_extra_where_clauses, SingleFieldData, State};
2use proc_macro2::TokenStream;
3use quote::quote;
4use syn::{parse::Result, DeriveInput};
5
6/// Provides the hook to expand `#[derive(DerefMut)]` into an implementation of `DerefMut`
7pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
8 let state = State::with_field_ignore_and_forward(
9 input,
10 trait_name,
11 quote!(::core::ops),
12 String::from("deref_mut"),
13 )?;
14 let SingleFieldData {
15 input_type,
16 trait_path,
17 casted_trait,
18 ty_generics,
19 field_type,
20 member,
21 info,
22 ..
23 } = state.assert_single_enabled_field();
24 let (body, generics) = if info.forward {
25 (
26 quote!(#casted_trait::deref_mut(&mut #member)),
27 add_extra_where_clauses(
28 &input.generics,
29 quote! {
30 where #field_type: #trait_path
31 },
32 ),
33 )
34 } else {
35 (quote!(&mut #member), input.generics.clone())
36 };
37 let (impl_generics, _, where_clause) = generics.split_for_impl();
38
39 Ok(quote! {
40 impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
41 {
42 #[inline]
43 fn deref_mut(&mut self) -> &mut Self::Target {
44 #body
45 }
46 }
47 })
48}
49