1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::utils::{
add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State,
};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{parse::Result, DeriveInput, Ident};
pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
let as_ref_type = &Ident::new("__AsRefT", Span::call_site());
let state = State::with_type_bound(
input,
trait_name,
quote!(::core::convert),
String::from("as_ref"),
AttrParams::ignore_and_forward(),
false,
)?;
let MultiFieldData {
fields,
input_type,
members,
infos,
trait_path,
impl_generics,
ty_generics,
where_clause,
..
} = state.enabled_fields_data();
let sub_items: Vec<_> = infos
.iter()
.zip(members.iter())
.zip(fields)
.map(|((info, member), field)| {
let field_type = &field.ty;
if info.forward {
let trait_path = quote!(#trait_path<#as_ref_type>);
let type_where_clauses = quote! {
where #field_type: #trait_path
};
let new_generics = add_where_clauses_for_new_ident(
&input.generics,
&[field],
as_ref_type,
type_where_clauses,
false,
);
let (impl_generics, _, where_clause) = new_generics.split_for_impl();
let casted_trait = quote!(<#field_type as #trait_path>);
(
quote!(#casted_trait::as_ref(&#member)),
quote!(#impl_generics),
quote!(#where_clause),
quote!(#trait_path),
quote!(#as_ref_type),
)
} else {
(
quote!(&#member),
quote!(#impl_generics),
quote!(#where_clause),
quote!(#trait_path<#field_type>),
quote!(#field_type),
)
}
})
.collect();
let bodies = sub_items.iter().map(|i| &i.0);
let impl_generics = sub_items.iter().map(|i| &i.1);
let where_clauses = sub_items.iter().map(|i| &i.2);
let trait_paths = sub_items.iter().map(|i| &i.3);
let return_types = sub_items.iter().map(|i| &i.4);
Ok(quote! {#(
impl#impl_generics #trait_paths for #input_type#ty_generics
#where_clauses
{
#[inline]
fn as_ref(&self) -> &#return_types {
#bodies
}
}
)*})
}