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}
56