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 = &param.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}