bon_macros/builder/builder_gen/builder_derives/mod.rs
1mod clone;
2mod debug;
3mod into;
4
5use super::top_level_config::{DeriveConfig, DerivesConfig};
6use super::BuilderGenCtx;
7use crate::util::prelude::*;
8use darling::ast::GenericParamExt;
9
10impl BuilderGenCtx {
11 pub(crate) fn builder_derives(&self) -> Result<TokenStream> {
12 let DerivesConfig { clone, debug, into } = &self.builder_type.derives;
13
14 let mut tokens = TokenStream::new();
15
16 if let Some(derive) = clone {
17 tokens.extend(self.derive_clone(derive));
18 }
19
20 if let Some(derive) = debug {
21 tokens.extend(self.derive_debug(derive));
22 }
23
24 if into.is_present() {
25 tokens.extend(self.derive_into()?);
26 }
27
28 Ok(tokens)
29 }
30
31 /// We follow the logic of the standard `#[derive(...)]` macros such as `Clone` and `Debug`.
32 /// They add bounds of their respective traits to every generic type parameter on the struct
33 /// without trying to analyze if that bound is actually required for the derive to work, so
34 /// it's a conservative approach.
35 ///
36 /// However, the user can also override these bounds using the `bounds(...)` attribute for
37 /// the specific derive.
38 fn where_clause_for_derive(
39 &self,
40 target_trait_bounds: &TokenStream,
41 derive: &DeriveConfig,
42 ) -> TokenStream {
43 let derive_specific_predicates = derive
44 .bounds
45 .as_ref()
46 .map(ToTokens::to_token_stream)
47 .unwrap_or_else(|| {
48 let bounds = self
49 .generics
50 .decl_without_defaults
51 .iter()
52 .filter_map(syn::GenericParam::as_type_param)
53 .map(|param| {
54 let ident = ¶m.ident;
55 quote! {
56 #ident: #target_trait_bounds
57 }
58 });
59
60 quote! {
61 #( #bounds, )*
62 }
63 });
64
65 let inherent_item_predicates = self.generics.where_clause_predicates();
66
67 quote! {
68 where
69 #( #inherent_item_predicates, )*
70 #derive_specific_predicates
71 }
72 }
73}