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 builder_ident = &self.builder_type.ident;
45        let state_var = &self.state_var;
46        let finish_fn_ident = &self.finish_fn.ident;
47
48        let builder_ty = quote! {
49            #builder_ident<#(#generic_args,)* #state_var>
50        };
51
52        let tokens = quote! {
53            #[automatically_derived]
54            impl<
55                #(#generics_decl,)*
56                #state_var: #state_mod::IsComplete
57            >
58            ::core::convert::From<#builder_ty> for #output_ty {
59                fn from(builder: #builder_ty) -> Self {
60                    #builder_ident::#finish_fn_ident(builder)
61                }
62            }
63        };
64
65        Ok(tokens)
66    }
67}