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
16 changes: 8 additions & 8 deletions benchmarks/compilation/results.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
| Command | Mean [s] | Min [s] | Max [s] | Relative |
| :------------------------------------- | ------------: | ------: | ------: | -----------: |
| `structs_100_fields_10 bon` | 2.321 卤 0.023 | 2.282 | 2.351 | 21.40 卤 1.92 |
| `structs_100_fields_10 typed-builder` | 1.677 卤 0.023 | 1.649 | 1.726 | 15.47 卤 1.40 |
| `structs_100_fields_10 derive_builder` | 1.043 卤 0.023 | 1.013 | 1.084 | 9.62 卤 0.88 |
| `structs_100_fields_10 ` | 0.135 卤 0.015 | 0.114 | 0.162 | 1.24 卤 0.18 |
| `structs_10_fields_50 bon` | 2.098 卤 0.022 | 2.065 | 2.135 | 19.35 卤 1.74 |
| `structs_10_fields_50 typed-builder` | 1.996 卤 0.021 | 1.970 | 2.029 | 18.41 卤 1.65 |
| `structs_10_fields_50 derive_builder` | 0.434 卤 0.012 | 0.415 | 0.450 | 4.00 卤 0.37 |
| `structs_10_fields_50 ` | 0.108 卤 0.010 | 0.096 | 0.129 | 1.00 |
| `structs_100_fields_10 bon` | 1.561 卤 0.018 | 1.515 | 1.580 | 17.55 卤 2.05 |
| `structs_100_fields_10 typed-builder` | 1.656 卤 0.019 | 1.617 | 1.678 | 18.62 卤 2.18 |
| `structs_100_fields_10 derive_builder` | 1.027 卤 0.016 | 1.006 | 1.056 | 11.55 卤 1.36 |
| `structs_100_fields_10 ` | 0.110 卤 0.011 | 0.096 | 0.130 | 1.23 卤 0.19 |
| `structs_10_fields_50 bon` | 1.493 卤 0.022 | 1.464 | 1.525 | 16.79 卤 1.97 |
| `structs_10_fields_50 typed-builder` | 1.994 卤 0.021 | 1.963 | 2.032 | 22.42 卤 2.62 |
| `structs_10_fields_50 derive_builder` | 0.418 卤 0.016 | 0.402 | 0.449 | 4.70 卤 0.58 |
| `structs_10_fields_50 ` | 0.089 卤 0.010 | 0.073 | 0.117 | 1.00 |
15 changes: 8 additions & 7 deletions bon-macros/src/builder/builder_gen/builder_derives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,34 @@ use crate::util::prelude::*;
use darling::ast::GenericParamExt;

impl BuilderGenCtx {
pub(crate) fn builder_derives(&self) -> Result<TokenStream> {
/// Returns a separate [`TokenStream`] for every generated item
pub(crate) fn builder_derives(&self) -> Result<Vec<TokenStream>> {
let DerivesConfig {
clone,
debug,
into,
into_future,
} = &self.builder_type.derives;

let mut tokens = TokenStream::new();
let mut items = vec![];

if let Some(derive) = clone {
tokens.extend(self.derive_clone(derive));
items.push(self.derive_clone(derive));
}

if let Some(derive) = debug {
tokens.extend(self.derive_debug(derive));
items.push(self.derive_debug(derive));
}

if into.is_present() {
tokens.extend(self.derive_into()?);
items.push(self.derive_into()?);
}

if let Some(derive) = into_future {
tokens.extend(self.derive_into_future(derive)?);
items.push(self.derive_into_future(derive)?);
}

Ok(tokens)
Ok(items)
}

/// We follow the logic of the standard `#[derive(...)]` macros such as `Clone` and `Debug`.
Expand Down
4 changes: 0 additions & 4 deletions bon-macros/src/builder/builder_gen/member/named.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,6 @@ impl NamedMember {
}
}

pub(crate) fn is(&self, other: &Self) -> bool {
self.index == other.index
}

pub(crate) fn merge_on_config(&mut self, on: &[OnConfig]) -> Result {
self.merge_config_default(on)?;

Expand Down
70 changes: 34 additions & 36 deletions bon-macros/src/builder/builder_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,46 +64,30 @@ impl BuilderGenCtx {
deprecated
)]);

let allows = self.allow_attrs.iter().cloned().chain([default_allows]);

// -- Postprocessing --
// Here we parse all items back and add the `allow` attributes to them.
let other_items = quote! {
#builder_decl
#builder_impl
#builder_derives
#state_mod
};

let other_items_str = other_items.to_string();

let other_items: syn::File = syn::parse2(other_items).map_err(|err| {
err!(
&Span::call_site(),
"bug in the `bon` crate: the macro generated code that contains syntax errors; \
please report this issue at our Github repository: \
https://github.com/elastio/bon;\n\
syntax error in generated code: {err:#?};\n\
generated code:\n\
```rust
{other_items_str}\n\
```",
)
})?;

let mut other_items = other_items.items;

for item in &mut other_items {
if let Some(attrs) = item.attrs_mut() {
attrs.extend(allows.clone());
}
}
let allows = self
.allow_attrs
.iter()
.cloned()
.chain([default_allows])
.collect::<Vec<_>>();

// Every item here is a single top-level item. We add the `allow`
// attributes to each of them directly. Previously this code converted
// the final token stream to string and parsed it to `syn::File`, which
// resulted in a significant performance hit. Ouch. Don't do that again!
let other_items = [builder_decl, builder_impl]
.into_iter()
.chain(builder_derives)
.chain([state_mod])
.map(|item| quote!(#(#allows)* #item));

let other_items = quote!(#(#other_items)*);

start_fn.attrs.extend(allows);

Ok(MacroOutput {
start_fn,
other_items: quote!(#(#other_items)*),
other_items,
})
}

Expand Down Expand Up @@ -148,7 +132,21 @@ impl BuilderGenCtx {
#allows
// Ignore dead code warnings because some setter/getter methods may
// not be used
#[allow(dead_code)]
#[allow(
dead_code,
// This is intentional. We want the builder syntax to compile away
clippy::inline_always,
// We don't want to avoid using `impl Trait` in the setter. This way
// the setter signature is easier to read, and anyway if you want to
// specify a type hint for the method that accepts an `impl Into`, then
// your design of this setter already went wrong.
clippy::impl_trait_in_params,
clippy::missing_const_for_fn,
// When having a field which has one of the prefixes listed by
// `clippy::wrong_self_convention` you will end up getting said lint
// warning in your `bon::Builder` because we take self by value.
clippy::wrong_self_convention,
)]
#[automatically_derived]
impl<
#(#generics_decl,)*
Expand Down
27 changes: 6 additions & 21 deletions bon-macros/src/builder/builder_gen/setters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,20 +458,6 @@ impl<'a> SettersCtx<'a> {

quote_spanned! {self.member.span=>
#( #docs )*
#[allow(
// This is intentional. We want the builder syntax to compile away
clippy::inline_always,
// We don't want to avoid using `impl Trait` in the setter. This way
// the setter signature is easier to read, and anyway if you want to
// specify a type hint for the method that accepts an `impl Into`, then
// your design of this setter already went wrong.
clippy::impl_trait_in_params,
clippy::missing_const_for_fn,
// When having a field which has one of the prefixes listed by
// `clippy::wrong_self_convention` you will end up getting said lint
// warning in your `bon::Builder` because we take self by value.
clippy::wrong_self_convention,
)]
#[inline(always)]
#(#fn_modifiers)* fn #name(#maybe_mut #self_, #( #pats: #types ),*) -> #return_type
#where_clause
Expand Down Expand Up @@ -700,13 +686,12 @@ fn well_known_default(ty: &syn::Type) -> Option<syn::Expr> {
Some(value)
}

/// Unfortunately there is no `syn::Parse` impl for `PatIdent` directly,
/// so we use this workaround instead.
fn pat_ident(ident_name: &'static str) -> syn::PatIdent {
let ident = syn::Ident::new(ident_name, Span::call_site());
let pat: syn::Pat = syn::parse_quote!(#ident);
match pat {
syn::Pat::Ident(pat_ident) => pat_ident,
_ => unreachable!("can't parse something else than PatIdent here: {pat:?}"),
syn::PatIdent {
attrs: vec![],
by_ref: None,
mutability: None,
ident: syn::Ident::new(ident_name, Span::call_site()),
subpat: None,
}
}
Loading
Loading