frame_support_procedural/no_bound/
clone.rs1use syn::spanned::Spanned;
19
20pub fn derive_clone_no_bound(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
22 let input = syn::parse_macro_input!(input as syn::DeriveInput);
23
24 let name = &input.ident;
25 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
26
27 let impl_ = match input.data {
28 syn::Data::Struct(struct_) => match struct_.fields {
29 syn::Fields::Named(named) => {
30 let fields = named.named.iter().map(|i| &i.ident).map(|i| {
31 quote::quote_spanned!(i.span() =>
32 #i: ::core::clone::Clone::clone(&self.#i)
33 )
34 });
35
36 quote::quote!( Self { #( #fields, )* } )
37 },
38 syn::Fields::Unnamed(unnamed) => {
39 let fields =
40 unnamed.unnamed.iter().enumerate().map(|(i, _)| syn::Index::from(i)).map(|i| {
41 quote::quote_spanned!(i.span() =>
42 ::core::clone::Clone::clone(&self.#i)
43 )
44 });
45
46 quote::quote!( Self ( #( #fields, )* ) )
47 },
48 syn::Fields::Unit => {
49 quote::quote!(Self)
50 },
51 },
52 syn::Data::Enum(enum_) => {
53 let variants = enum_.variants.iter().map(|variant| {
54 let ident = &variant.ident;
55 match &variant.fields {
56 syn::Fields::Named(named) => {
57 let captured = named.named.iter().map(|i| &i.ident);
58 let cloned = captured.clone().map(|i| {
59 ::quote::quote_spanned!(i.span() =>
60 #i: ::core::clone::Clone::clone(#i)
61 )
62 });
63 quote::quote!(
64 Self::#ident { #( ref #captured, )* } => Self::#ident { #( #cloned, )*}
65 )
66 },
67 syn::Fields::Unnamed(unnamed) => {
68 let captured = unnamed
69 .unnamed
70 .iter()
71 .enumerate()
72 .map(|(i, f)| syn::Ident::new(&format!("_{}", i), f.span()));
73 let cloned = captured.clone().map(|i| {
74 quote::quote_spanned!(i.span() =>
75 ::core::clone::Clone::clone(#i)
76 )
77 });
78 quote::quote!(
79 Self::#ident ( #( ref #captured, )* ) => Self::#ident ( #( #cloned, )*)
80 )
81 },
82 syn::Fields::Unit => quote::quote!( Self::#ident => Self::#ident ),
83 }
84 });
85
86 quote::quote!(match self {
87 #( #variants, )*
88 })
89 },
90 syn::Data::Union(_) => {
91 let msg = "Union type not supported by `derive(CloneNoBound)`";
92 return syn::Error::new(input.span(), msg).to_compile_error().into()
93 },
94 };
95
96 quote::quote!(
97 const _: () = {
98 #[automatically_derived]
99 #[allow(deprecated)]
100 impl #impl_generics ::core::clone::Clone for #name #ty_generics #where_clause {
101 fn clone(&self) -> Self {
102 #impl_
103 }
104 }
105 };
106 )
107 .into()
108}