frame_support_procedural/no_bound/
default.rs1use proc_macro2::Span;
19use quote::{quote, quote_spanned};
20use syn::{spanned::Spanned, Data, DeriveInput, Fields};
21
22pub fn derive_default_no_bound(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
24 let input = syn::parse_macro_input!(input as DeriveInput);
25
26 let name = &input.ident;
27
28 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
29
30 let impl_ = match input.data {
31 Data::Struct(struct_) => match struct_.fields {
32 Fields::Named(named) => {
33 let fields = named.named.iter().map(|field| &field.ident).map(|ident| {
34 quote_spanned! {ident.span() =>
35 #ident: ::core::default::Default::default()
36 }
37 });
38
39 quote!(Self { #( #fields, )* })
40 },
41 Fields::Unnamed(unnamed) => {
42 let fields = unnamed.unnamed.iter().map(|field| {
43 quote_spanned! {field.span()=>
44 ::core::default::Default::default()
45 }
46 });
47
48 quote!(Self( #( #fields, )* ))
49 },
50 Fields::Unit => {
51 quote!(Self)
52 },
53 },
54 Data::Enum(enum_) => {
55 if enum_.variants.is_empty() {
56 return syn::Error::new_spanned(name, "cannot derive Default for an empty enum")
57 .to_compile_error()
58 .into()
59 }
60
61 let default_variants = enum_
63 .variants
64 .into_iter()
65 .filter(|variant| variant.attrs.iter().any(|attr| attr.path().is_ident("default")))
66 .collect::<Vec<_>>();
67
68 match &*default_variants {
69 [] => return syn::Error::new(
70 name.clone().span(),
71 "no default declared, make a variant default by placing `#[default]` above it",
72 )
73 .into_compile_error()
74 .into(),
75 [default_variant] => {
77 let variant_attrs = default_variant
78 .attrs
79 .iter()
80 .filter(|a| a.path().is_ident("default"))
81 .collect::<Vec<_>>();
82
83 if let [first_attr, second_attr, additional_attrs @ ..] = &*variant_attrs {
85 let mut err =
86 syn::Error::new(Span::call_site(), "multiple `#[default]` attributes");
87
88 err.combine(syn::Error::new_spanned(first_attr, "`#[default]` used here"));
89
90 err.extend([second_attr].into_iter().chain(additional_attrs).map(
91 |variant| {
92 syn::Error::new_spanned(variant, "`#[default]` used again here")
93 },
94 ));
95
96 return err.into_compile_error().into()
97 }
98
99 let variant_ident = &default_variant.ident;
100
101 let fully_qualified_variant_path = quote!(Self::#variant_ident);
102
103 match &default_variant.fields {
104 Fields::Named(named) => {
105 let fields =
106 named.named.iter().map(|field| &field.ident).map(|ident| {
107 quote_spanned! {ident.span()=>
108 #ident: ::core::default::Default::default()
109 }
110 });
111
112 quote!(#fully_qualified_variant_path { #( #fields, )* })
113 },
114 Fields::Unnamed(unnamed) => {
115 let fields = unnamed.unnamed.iter().map(|field| {
116 quote_spanned! {field.span()=>
117 ::core::default::Default::default()
118 }
119 });
120
121 quote!(#fully_qualified_variant_path( #( #fields, )* ))
122 },
123 Fields::Unit => fully_qualified_variant_path,
124 }
125 },
126 [first, additional @ ..] => {
127 let mut err = syn::Error::new(Span::call_site(), "multiple declared defaults");
128
129 err.combine(syn::Error::new_spanned(first, "first default"));
130
131 err.extend(
132 additional
133 .into_iter()
134 .map(|variant| syn::Error::new_spanned(variant, "additional default")),
135 );
136
137 return err.into_compile_error().into()
138 },
139 }
140 },
141 Data::Union(union_) =>
142 return syn::Error::new_spanned(
143 union_.union_token,
144 "Union type not supported by `derive(DefaultNoBound)`",
145 )
146 .to_compile_error()
147 .into(),
148 };
149
150 quote!(
151 const _: () = {
152 #[automatically_derived]
153 #[allow(deprecated)]
154 impl #impl_generics ::core::default::Default for #name #ty_generics #where_clause {
155 fn default() -> Self {
156 #impl_
157 }
158 }
159 };
160 )
161 .into()
162}