NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #1167 most downloaded on crates.io
Next-gen compile-time-checked builder generator, named function's arguments, and more!
Last release 5 days ago
02 Oct 2026
Release timing varies
gaps range from 1 weeks to 3 months
Nearly every release is documented
notes for 49 of 50 stable releases
Nothing withdrawn
no release was ever pulled
2 years old
51 releases · first in 2024
Improve the compile time of the builder macros and the code they generate by ~30%
Strip the r# prefix from raw identifiers in derive(Debug) ( #402 ). Thanks @MaxFreedomPollard for the contribution!
r# prefix from raw identifiers in derive(Debug) (#402). Thanks @MaxFreedomPollard for the contribution!One column per month.
The new MSRV also comes with the deprecation of the implied-bounds cargo feature. Implied bounds are now added by default without any feature gate, so…
This release raises the minimum supported Rust version from 1.59.0 to 1.88.0. If you are on an older compiler, stay on bon@3.9.
The new MSRV also comes with the deprecation of the implied-bounds cargo feature. Implied bounds are now added by default without any feature gate, so be sure to remove that feature from your Cargo.toml if you have it enabled. It's currently a no-op, and it won't be removed until a major release, for which there are no plans yet.
The MSRV bump comes from the darling@0.24 update, which is the first version that uses syn@3.0.
default switch in the on(...) clause (#398). Thanks @ChrisJr404 for the contribution!1.88.0, move to the 2024 edition, update to syn@3.0 and darling@0.24 (#399)implied-bounds cargo feature. Implied bounds are now generated by default (#399)Fix clippy::missing_docs_in_private_items triggering for start_fn members
Fix rust-analyzer "Go to Definition" inside #[builder] functions
This is purely a minutiae update with zero changes to the Rust API. Enjoy the stability 🍸.
Introduce a new experimental attribute builder(generics(setters)) for overwriting generic types on the builder. ( #364 , #368 , #370 ). Thanks @dflems
Don't attempt to compile big default value showcases as ignored rust doctests
Fix clippy::wrong_self_convention warning for fields with is_ prefix etc. ( #349 ). Thanks @nicmue for the contribution!
This release brings some rustdoc improvements and no other visible API changes except that rustc and clippy will start reporting some more true-positi
This release brings some rustdoc improvements and no other visible API changes except that rustc and clippy will start reporting some more true-positive lints. For example builder methods defined via an impl block annotated with #[bon] will now be correctly reported as unused if they are not used. Also, using a private type in a public builder method will trigger a private_interfaces lint now.
This is all thanks to the updated span handling design researched and implemented by @Eisverygoodletter. It's not clear what other new lints the new span handling may trigger in other realworld codebases. If you see a lint from the code generated by bon that you think shouldn't be there, please, open an issue, and it'll be fixed as soon as possible!
Add missing lifetime replacement for generic param declarations on derive(IntoFuture) impl block
This is a small patch release to make bon easier to package for Debian.
Add support for #[builder(derive(IntoFuture(Box)))] ( #322 ). This allows calling builder.await instead of builder.call().await . Thanks @jakubadamw f
#[builder(derive(IntoFuture(Box)))] (#322).builder.await instead of builder.call().await. Thanks @jakubadamw for the contribution!where clause forwarding to #[builder(derive(Into))] (#325)This is a regular maintenance release with no essential API/behavior changes. Enjoy the stability 😄.
This is a regular maintenance release with no essential API/behavior changes. Enjoy the stability 😄.
darling (crate for parsing the attributes) from 0.20 to 0.21 and other internal dependencies (#317, #320, #304)iai to iai-callgrind for high-precision benchmarking of bon (#311). iai-callgrind is a better maintained alternative to iai, but in any case, both deserve a huge thanks for providing the benchmarking capabilities for bon!clippy::or_fun_call lint from the nightly toolchain (#316)Improve error reporting when using the #[bon::builder] fully qualified attribute inside of impl blocks
#[bon::builder] fully qualified attribute inside of impl blocks (#297)Fix missing support for #[builder(field)] with #[builder(const)]
#[builder(field)] with #[builder(const)] (#291)Propagate #[target_feature] attributes on #[builder]-generated finishing functions (#284). Thanks @Lilyyy411 for the contribution!
#[target_feature] attributes on #[builder]-generated finishing functions (#284). Thanks @Lilyyy411 for the contribution!const token order in code generated by #[builder(const)] (#288)Propagate #[track_caller] to the generated finishing function from the underlying function/method (#282). Thanks @Lilyyy411 for the contribution!
#[track_caller] to the generated finishing function from the underlying function/method (#282). Thanks @Lilyyy411 for the contribution!Add very limited support for #[builder(const)] (#279). See the updated docs here
Small fix for rust-analyzer syntax highlighting of parameters for functions annotated with #[builder] (#275). This doesn't fix the problem fully since
#[builder] (#275).
This doesn't fix the problem fully since function parameters are now assigned "variable" semantic token type instead of "parameter". However, it's already better than "struct" that they were assigned before this fix. Created an issue in rust-analyzer with more details and to get the full fix of this problem: rust-lang/rust-analyzer#19556.Delay the privatizing (i.e. renaming of the original function to __orig_{fn_name}) until after all other macros are expanded (#269). Also removed the
__orig_{fn_name}) until after all other macros are expanded (#269). Also removed the warnings for #[tracing::instrument] users introduced in #264. This is because with this patch there will be no difference whether you place #[tracing::instrument] after or before the #[builder] attribute - all other proc macros on the function will see the original function name.Introduce setters(doc(default(skip))) attribute to skip the inclusion of the default value in the generated docs for setters (#265). See the updated d
setters(doc(default(skip))) attribute to skip the inclusion of the default value in the generated docs for setters (#265). See the updated docs here.#[tracing::instrument] is placed after the #[builder] instead of before (#264). This should prevent the papercut where tracing::instrument assigns the span name with the ugly __orig_ prefix in the name.#[builder] attributes getting ignored on free functions (#263)Stabilize the current [#[builder(getter)]](https://bon-rs.com/reference/builder/member/getter) attribute MVP (#251). The cargo feature experimental-ge
#[builder(getter)] attribute MVP (#251).
The cargo feature experimental-getters is no longer needed and is now no-op.self receiver and start_fn members available as official fields on the builder (#250).
Check the new documentation page about native fields.#[builder(derive(Into))] attribute to generate an impl From<Builder> for T (#248).
See the updated "Inspecting" guide page now known as Derives for Builders and the updated #[builder(derive)] reference.100$ a month!1$ a month!Fix syntax errors caused by PascalCasification when generating code for members named self_
self_ (#238)Fix clippy::empty_enum triggering on nightly with feature(never_type) enabled
clippy::empty_enum triggering on nightly with feature(never_type) enabled (#234)Add clone, copy, deref configs support in #[builder(getter)] (see new docs)
clone, copy, deref configs support in #[builder(getter)] (see new docs) (#229)Add #[builder(getter(...))] attribute to define getters for already set members. See Getters guide for details (#222) (#226). Thanks @lazkindness for
#[builder(getter(...))] attribute to define getters for already set members. See Getters guide for details (#222) (#226). Thanks @lazkindness for the contribution!Make generated identifiers of private fields deterministic. This is important for the Buck build system and probably for Bazel as well
Add [#[builder(field)]](https://bon-rs.com/reference/builder/member/field) to define custom private fields on the builder type. See Custom Fields guid
#[builder(field)] to define custom private fields on the builder type. See Custom Fields guide for details (#207)bons test suite (#215)Fix unexpected_cfgs lint coming from #[cfg(rust_analyzer)] on the latest nightly
unexpected_cfgs lint coming from #[cfg(rust_analyzer)] on the latest nightly (#212)Fix handling of lifetimes not used in fn param types
All the breaking changes are very unlikely to actually break your code that was written against the v2 version of bon. 99% of users should be able to…
See the most interesting changes described in Bon 3.0 Release blog post.
All the breaking changes are very unlikely to actually break your code that was written against the v2 version of bon. 99% of users should be able to update without any migration.
🎉🎉 Stabilize the builder's typestate API allowing for custom builder extensions. This is the main theme of this release. This new API brings the flexibility to a whole new level 🚀 🚀 (#145)
Improve rustdoc output. See the rustoc examples and comparison in the Alternatives section (#145)
Add info that the member is required or optional.
For members with default values show the default value in the docs.
For optional members provide links to {member}(T) and maybe_{member}(Option<T>) setters.
Remove __ prefixes for generic types and lifetimes from internal symbols. Instead, the prefixes added only if the macro detects a name collision.
⚠️ Breaking. Reject unnecessary empty attributes e.g. #[builder()] or #[builder] with no parameters on a member (#145)
⚠️ Breaking. Reject square brackets and curly braces delimiters for builder_type, finish_fn, start_fn and on attributes syntax. Only parentheses are accepted e.g. #[builder(finish_fn(...))] or #[builder(on(...))]. This no longer works: #[builder(finish_fn[...])] or #[builder(on{...})] (#145)
⚠️ Breaking. Reject non-consecutive on(...) clauses. For example, the following now generates a compile error: #[builder(on(String, into), finish_fn = build, on(Vec<_>, into))], because there is a finish_fn = ... between on(...) clauses. (#155)
⚠️ Breaking. #[builder(derive(Clone, Debug))] now generates impl blocks that follow the behaviour of standard Clone and Debug derives in that it conservatively adds Clone/Debug trait bounds for all the generic types declared on the original item (struct or function). Previously no additional bounds were required on Clone and Debug impls. See the Added section for details on the way to override these bounds with #[builder(derive(Clone/Debug(bounds(...))))] (#145)
⚠️ Breaking. The name of the builder struct generated for methods named builder changed from TBuilderBuilder to just TBuilder making methods named builder work the same as methods named new. (#145)
⚠️ Breaking. The type of the builder is now dependent on the order of the setters' invocation. This may only break code like the following:
let builder = if condition {
Foo::builder().a(1).b(2)
} else {
Foo::builder().b(1).a(2)
};
builder.build();
This is because the types of the builders returned from the branches are the following:
FooBuilder<SetB<SetA>> (if branch)FooBuilder<SetA<SetB>> (else branch)We believe such code should generally be very rare and even if it breaks, it's easy to fix it by reordering the setter method calls. This compromise was accepted as a design tradeoff such that the builder's type signature becomes simpler, the generated documentation becomes much less noisy, it removes an annoying special case for the builder of just one member, and it improves the type-checking performance considerably compared to the previous approach that used tuples to represent the type state. (#145)
⚠️ Breaking. Remove support for #[bon::builder] proc-macro attribute on top of a struct. Use #[derive(bon::Builder)] for that instead. This syntax has been deprecated since 2.1 and it is now removed as part of a major version cleanup (#145)
⚠️ Breaking. Remove #[builder(expose_positional_fn = positional_fn_name)] attribute. Use #[builder(start_fn = builder_fn_name)] instead, since this attribute works additively keeping the function with positional arguments under the attribute unchanged. (#153)
⚠️ Breaking. Builder macros now generate additional mod builder_name {} where builder_name is the snake_case version of the name of the builder struct. This new module contains the type state API of the builder. There is a low probability that this new module name may conflict with existing symbols in your scope, so this change is marked as breaking (#145)
Add #[builder(builder_type(vis = "...", doc { ... }))] that allows overriding the visibility and docs of the builder struct (#145)
Add #[builder(finish_fn(vis = "...", doc { ... } ))] that allows overriding the visibility and docs of the finishing function (#145)
Add #[builder(start_fn(doc { ... }))] that allows overriding the docs of the starting function (#145)
Add #[builder(with = closure)] syntax to customize setters with a closure. If the closure returns a Result<_, E> the setters become fallible (#145)
Add #[builder(with = Some)], #[builder(with = FromIterator::from_iter)], #[builder(with = <_>::from_iter)] syntax support for two well-known functions that will probably be used frequently (#157)
Add #[builder(required)] for Option fields to opt out from their special handling which makes bon treat them as regular required fields. It's also available at the top-level via #[builder(on(_, required))] (#145, #155)
Add #[builder(crate = path::to::bon)] and #[bon(crate = path::to::bon)] to allow overriding the path to bon crate used in the generated code, which is useful for the cases when bon macros are wrapped by other macros (#153)
Add #[builder(state_mod)] to configure the builder's type state API module name, visibility and docs (#145)
🔬 Experimental. Add #[builder(overwritable)] and #[builder(on(..., overwritable)] to make it possible to call setters multiple times for the same member. This attribute is available under the cargo feature "experimental-overwritable". The fate of this feature depends on your feedback in the tracking issue #149. Please, let us know if you have a use case for this attribute! (#145)
Add #[builder(setters)] to fine-tune the setters names, visibility and docs (#145)
Add #[builder(derive(Clone/Debug(bounds(...))] to allow overriding trait bounds on the Clone/Debug impl block of the builder (#145)
Add inheritance of #[allow()] and #[expect()] lint attributes to all generated items. This is useful to suppress any lints coming from the generated code. Although, lints coming from the generated code are generally considered defects in bon and should be reported via a Github issue, but this provides an easy temporary workaround for the problem (#145)
unused_mut lints coming from #[builder] on a method that takes mut self (#197)#[cfg/cfg_attr()] not being expanded when used on function arguments with doc comments or other attributes (#145)bon macro panics due to an internal bug, the macro will try to generate a fallback for IDEs to still provide intellisense (#145)elastio.github.io/bon to a custom domain bon-rs.com (#158)umami for the docs website (#158)All the breaking changes are very unlikely to actually break your code that was written against the v2 version of bon. 99% of users should be able to…
All the breaking changes are very unlikely to actually break your code that was written against the v2 version of bon. 99% of users should be able to update without any migration.
🎉🎉 Stabilize the builder's typestate API allowing for custom builder extensions. This is the main theme of this release. This new API brings the flexibility to a whole new level 🚀 🚀 (#145)
Improve rustdoc output. See the rustoc examples and comparison in the Alternatives section (#145)
Add info that the member is required or optional.
For members with default values show the default value in the docs.
For optional members provide links to {member}(T) and maybe_{member}(Option<T>) setters.
Remove __ prefixes for generic types and lifetimes from internal symbols. Instead, the prefixes added only if the macro detects a name collision.
⚠️ Breaking. Reject unnecessary empty attributes e.g. #[builder()] or #[builder] with no parameters on a member (#145)
⚠️ Breaking. Reject square brackets and curly braces delimiters for builder_type, finish_fn, start_fn and on attributes syntax. Only parentheses are accepted e.g. #[builder(finish_fn(...))] or #[builder(on(...))]. This no longer works: #[builder(finish_fn[...])] or #[builder(on{...})] (#145)
⚠️ Breaking. Reject non-consecutive on(...) clauses. For example, the following now generates a compile error: #[builder(on(String, into), finish_fn = build, on(Vec<_>, into))], because there is a finish_fn = ... between on(...) clauses. (#155)
⚠️ Breaking. #[builder(derive(Clone, Debug))] now generates impl blocks that follow the behaviour of standard Clone and Debug derives in that it conservatively adds Clone/Debug trait bounds for all the generic types declared on the original item (struct or function). Previously no additional bounds were required on Clone and Debug impls. See the Added section for details on the way to override these bounds with #[builder(derive(Clone/Debug(bounds(...))))] (#145)
⚠️ Breaking. The name of the builder struct generated for methods named builder changed from TBuilderBuilder to just TBuilder making methods named builder work the same as methods named new. (#145)
⚠️ Breaking. The type of the builder is now dependent on the order of the setters' invocation. This may only break code like the following:
let builder = if condition {
Foo::builder().a(1).b(2)
} else {
Foo::builder().b(1).a(2)
};
builder.build();
This is because the types of the builders returned from the branches are the following:
FooBuilder<SetB<SetA>> (if branch)FooBuilder<SetA<SetB>> (else branch)We believe such code should generally be very rare and even if it breaks, it's easy to fix it by reordering the setter method calls. This compromise was accepted as a design tradeoff such that the builder's type signature becomes simpler, the generated documentation becomes much less noisy, it removes an annoying special case for the builder of just one member, and it improves the type-checking performance considerably compared to the previous approach that used tuples to represent the type state. (#145)
⚠️ Breaking. Remove support for #[bon::builder] proc-macro attribute on top of a struct. Use #[derive(bon::Builder)] for that instead. This syntax has been deprecated since 2.1 and it is now removed as part of a major version cleanup (#145)
⚠️ Breaking. Remove #[builder(expose_positional_fn = positional_fn_name)] attribute. Use #[builder(start_fn = builder_fn_name)] instead, since this attribute works additively keeping the function with positional arguments under the attribute unchanged. (#153)
⚠️ Breaking. Builder macros now generate additional mod builder_name {} where builder_name is the snake_case version of the name of the builder struct. This new module contains the type state API of the builder. There is a low probability that this new module name may conflict with existing symbols in your scope, so this change is marked as breaking (#145)
Add #[builder(builder_type(vis = "...", doc { ... }))] that allows overriding the visibility and docs of the builder struct (#145)
Add #[builder(finish_fn(vis = "...", doc { ... } ))] that allows overriding the visibility and docs of the finishing function (#145)
Add #[builder(start_fn(doc { ... }))] that allows overriding the docs of the starting function (#145)
Add #[builder(with = closure)] syntax to customize setters with a closure. If the closure returns a Result<_, E> the setters become fallible (#145)
Add #[builder(with = Some)], #[builder(with = FromIterator::from_iter)], #[builder(with = <_>::from_iter)] syntax support for two well-known functions that will probably be used frequently (#157)
Add #[builder(required)] for Option fields to opt out from their special handling which makes bon treat them as regular required fields. It's also available at the top-level via #[builder(on(_, required))] (#145, #155)
Add #[builder(crate = path::to::bon)] and #[bon(crate = path::to::bon)] to allow overriding the path to bon crate used in the generated code, which is useful for the cases when bon macros are wrapped by other macros (#153)
Add #[builder(state_mod)] to configure the builder's type state API module name, visibility and docs (#145)
🔬 Experimental. Add #[builder(overwritable)] and #[builder(on(..., overwritable)] to make it possible to call setters multiple times for the same member. This attribute is available under the cargo feature "experimental-overwritable". The fate of this feature depends on your feedback in the tracking issue #149. Please, let us know if you have a use case for this attribute! (#145)
Add #[builder(setters)] to fine-tune the setters names, visibility and docs (#145)
Add #[builder(derive(Clone/Debug(bounds(...))] to allow overriding trait bounds on the Clone/Debug impl block of the builder (#145)
Add inheritance of #[allow()] and #[expect()] lint attributes to all generated items. This is useful to suppress any lints coming from the generated code. Although, lints coming from the generated code are generally considered defects in bon and should be reported via a Github issue, but this provides an easy temporary workaround for the problem (#145)
#[cfg/cfg_attr()] not being expanded when used on function arguments with doc comments or other attributes (#145)bon macro panics due to an internal bug, the macro will try to generate a fallback for IDEs to still provide intellisense (#145)elastio.github.io/bon to a custom domain bon-rs.com (#158)umami for the docs website (#158)See the blog post for this release that describes some of the most notable changes in detail.
See the blog post for this release that describes some of the most notable changes in detail.
start_fn and finish_fn (#125)#[allow()/expect()] attributes written by the user on the top-level to the generated items (#125)clippy::future_not_send lint (#125)#[builder(derive(Debug, Clone))] didn't validate for all members to implement Clone/Debug if these members were of reference or generic types (#125)Lower MSRV from 1.70.0 to 1.59.0
The #[bon::builder] attribute was deprecated on structs. The new [#[derive(bon::Builder)]](https://bon-rs.com/reference/builder) should be used to der…
See the blog post for this release that describes some of the most notable changes in detail.
The #[bon::builder] attribute was deprecated on structs. The new #[derive(bon::Builder)] should be used to derive a builder from a struct. Starting with bon 2.3 (next minor release) all usages of #[bon::builder] on structs will generate deprecation warnings. (#99).
There is a CLI to assist in migrating to the new syntax. See the release blog post for details about that.
Add the top-level #[builder(derive(...))] attribute to be able to derive Clone and Debug for the builder type itself (#113)
Add support for conditional compilation with cfg/cfg_attr (#99)
#[derive(Builder)] syntax should now be easier for Rust Rover to analyze (#99)Option type (i.e. the Option type that was renamed to make the builder macro not detect it as Option) was still optional. (#99)Set MSRV to 1.70.0. Note that we plan to set an even lower MSRV. This is just an initial attempt to define the MSRV that should be good enough in the
See the blog post for this release that describes some of the most notable changes in detail.
See the blog post for this release that describes some of the most notable changes in detail.
#[must_use] on the build() method for structs and call() for functions (if the original function has #[must_use]) (#82). Thanks @EdJoPaTo for the contribution!bon's generated code type-checking performance and improve error messages (#84)clippy::impl_trait_in_params (#80). Thanks @EdJoPaTo for the contribution!#[must_use] (#87)Add a new section "`None` literals inference" to docs for "Into Conversions In-Depth"
None literals inference" to docs for "Into Conversions In-Depth"See the blog post for details.
See the blog post for details.
### Other - Remove unnecessary const block (#52) - Small cleanup
Add #[builder(skip)] attribute to skip generating setters
Add no_std support (#36). Thanks @danielschemmel for the contribution!
Explicitly specify the minimum required version of the darling dependency
Add #[must_use] to the builder and other small improvements
#[must_use] to the builder and other small improvements (#26)new() method is now hidden by default and the Builder type name is the same as when #[builder] is on top of a struct
#[builder] is on top of a struct (#19)Fix missing captured generics on an impl block that aren't referenced in the method
Fix a bug of the Default trait requirement for types under an Option
Fix handling of raw identifiers
Initial release 🎉. See the `bon` crate overview for details.
bon crate overview for details.Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →