Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crate-ci/typos@v1.28.1
- uses: crate-ci/typos@v1.30.1

website-build:
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions bon-macros/src/bon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub(crate) fn generate(params: TokenStream, item: TokenStream) -> TokenStream {
}

pub(crate) fn try_generate(params: TokenStream, item: TokenStream) -> Result<TokenStream> {
let item: syn::Item = syn::parse2(item)?;
let item = syn::parse2(item)?;

let ctx = ExpandCfg {
current_macro: format_ident!("bon"),
Expand All @@ -26,7 +26,7 @@ pub(crate) fn try_generate(params: TokenStream, item: TokenStream) -> Result<Tok
let params = NestedMeta::parse_meta_list(input.config)?;
let params = FromMeta::from_list(&params)?;

match input.item {
match *input.item {
syn::Item::Impl(item_impl) => builder::item_impl::generate(params, item_impl),
_ => bail!(
&input.item,
Expand Down
261 changes: 0 additions & 261 deletions bon-macros/src/builder/builder_gen/builder_derives.rs

This file was deleted.

103 changes: 103 additions & 0 deletions bon-macros/src/builder/builder_gen/builder_derives/clone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use super::BuilderGenCtx;
use crate::builder::builder_gen::top_level_config::DeriveConfig;
use crate::util::prelude::*;

impl BuilderGenCtx {
pub(super) fn derive_clone(&self, derive: &DeriveConfig) -> TokenStream {
let bon = &self.bon;
let generics_decl = &self.generics.decl_without_defaults;
let generic_args = &self.generics.args;
let builder_ident = &self.builder_type.ident;

let clone = quote!(::core::clone::Clone);

let clone_receiver = self.receiver().map(|receiver| {
let ty = &receiver.without_self_keyword;
quote! {
__unsafe_private_receiver: <#ty as #clone>::clone(&self.__unsafe_private_receiver),
}
});

let clone_start_fn_args = self.start_fn_args().next().map(|_| {
let types = self.start_fn_args().map(|arg| &arg.base.ty.norm);
let indices = self.start_fn_args().map(|arg| &arg.index);

quote! {
// We clone named members individually instead of cloning
// the entire tuple to improve error messages in case if
// one of the members doesn't implement `Clone`. This avoids
// a sentence that say smth like
// ```
// required for `(...big type...)` to implement `Clone`
// ```
__unsafe_private_start_fn_args: (
#( <#types as #clone>::clone(&self.__unsafe_private_start_fn_args.#indices), )*
),
}
});

let where_clause = self.where_clause_for_derive(&clone, derive);
let state_mod = &self.state_mod.ident;

let clone_named_members = self.named_members().map(|member| {
let member_index = &member.index;

// The type hint here is necessary to get better error messages
// that point directly to the type that doesn't implement `Clone`
// in the input code using the span info from the type hint.
let ty = member.underlying_norm_ty();

quote! {
#bon::__::better_errors::clone_member::<#ty>(
&self.__unsafe_private_named.#member_index
)
}
});

let clone_fields = self.custom_fields().map(|member| {
let member_ident = &member.ident;
let member_ty = &member.norm_ty;

quote! {
// The type hint here is necessary to get better error messages
// that point directly to the type that doesn't implement `Clone`
// in the input code using the span info from the type hint.
#member_ident: <#member_ty as #clone>::clone(&self.#member_ident)
}
});

let state_var = &self.state_var;

quote! {
#[automatically_derived]
impl<
#(#generics_decl,)*
#state_var: #state_mod::State
>
#clone for #builder_ident<
#(#generic_args,)*
#state_var
>
#where_clause
{
fn clone(&self) -> Self {
Self {
__unsafe_private_phantom: ::core::marker::PhantomData,
#clone_receiver
#clone_start_fn_args
#( #clone_fields, )*

// We clone named members individually instead of cloning
// the entire tuple to improve error messages in case if
// one of the members doesn't implement `Clone`. This avoids
// a sentence that say smth like
// ```
// required for `(...big type...)` to implement `Clone`
// ```
__unsafe_private_named: ( #( #clone_named_members, )* ),
}
}
}
}
}
}
Loading