referrerpolicy=no-referrer-when-downgrade

frame_support_procedural/no_bound/
default.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use proc_macro2::Span;
19use quote::{quote, quote_spanned};
20use syn::{spanned::Spanned, Data, DeriveInput, Fields};
21
22/// Derive Default but do not bound any generic.
23pub 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			// all #[default] attrs with the variant they're on; i.e. a var
62			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				// only one variant with the #[default] attribute set
76				[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					// check that there is only one #[default] attribute on the variant
84					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}