derive_more/
deref.rs

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(Deref)]` into an implementation of `Deref`
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        trait_name.to_lowercase(),
13    )?;
14    let SingleFieldData {
15        input_type,
16        field_type,
17        trait_path,
18        casted_trait,
19        ty_generics,
20        member,
21        info,
22        ..
23    } = state.assert_single_enabled_field();
24
25    let (target, body, generics) = if info.forward {
26        (
27            quote!(#casted_trait::Target),
28            quote!(#casted_trait::deref(&#member)),
29            add_extra_where_clauses(
30                &input.generics,
31                quote! {
32                    where #field_type: #trait_path
33                },
34            ),
35        )
36    } else {
37        (
38            quote!(#field_type),
39            quote!(&#member),
40            input.generics.clone(),
41        )
42    };
43    let (impl_generics, _, where_clause) = generics.split_for_impl();
44
45    Ok(quote! {
46        impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
47        {
48            type Target = #target;
49            #[inline]
50            fn deref(&self) -> &Self::Target {
51                #body
52            }
53        }
54    })
55}