Skip to main content

bon_macros/builder/builder_gen/builder_derives/
into.rs

1use crate::builder::builder_gen::models::BuilderGenCtx;
2use crate::util::prelude::*;
3
4impl BuilderGenCtx {
5    pub(super) fn derive_into(&self) -> Result<TokenStream> {
6        if let Some(asyncness) = &self.finish_fn.asyncness {
7            bail!(
8                asyncness,
9                "`#[builder(derive(Into))` is not supported for async functions \
10                because `From::from()` method is a synchronous method"
11            )
12        }
13
14        if let Some(unsafety) = &self.finish_fn.unsafety {
15            bail!(
16                unsafety,
17                "`#[builder(derive(Into))` is not supported for unsafe functions \
18                because `From::from()` method is a safe method"
19            )
20        }
21
22        if let Some(arg) = self.finish_fn_args().next() {
23            bail!(
24                &arg.config.finish_fn.span(),
25                "`#[builder(derive(Into))` is incompatible with `#[builder(finish_fn)]` members \
26                because `From::from()` method accepts zero parameters"
27            )
28        }
29
30        let output_ty = match &self.finish_fn.output {
31            syn::ReturnType::Default => bail!(
32                &self.start_fn.ident,
33                "`#[builder(derive(Into))` is not supported for functions with the implicit unit return type; \
34                if you have a use case where it makes sense to implement `From<Builder> for ()`, \
35                please open an issue, and in the meantime annotate the function return type explicitly \
36                with `-> ()`"
37            ),
38            syn::ReturnType::Type(_, output_ty) => output_ty.as_ref(),
39        };
40
41        let state_mod = &self.state_mod.ident;
42        let generics_decl = &self.generics.decl_without_defaults;
43        let generic_args = &self.generics.args;
44        let where_clause = &self.generics.where_clause;
45        let builder_ident = &self.builder_type.ident;
46        let state_var = &self.state_var;
47        let finish_fn_ident = &self.finish_fn.ident;
48
49        let builder_ty = quote! {
50            #builder_ident<#(#generic_args,)* #state_var>
51        };
52
53        let tokens = quote! {
54            #[automatically_derived]
55            impl<
56                #(#generics_decl,)*
57                #state_var: #state_mod::IsComplete
58            >
59            ::core::convert::From<#builder_ty> for #output_ty
60            #where_clause
61            {
62                fn from(builder: #builder_ty) -> Self {
63                    #builder_ident::#finish_fn_ident(builder)
64                }
65            }
66        };
67
68        Ok(tokens)
69    }
70}