start_fn
​
Applies to: structs functions methods
Overrides name, visibility and docs for the starting function.
TIP
Don't confuse this with the member-level #[builder(start_fn)]
attribute.
When this attribute is used with fn
syntax, it additionally exposes the original function under the macro.
Short syntax configures just the name.
#[builder(start_fn = custom_name)]
Long syntax provides more flexibility. All keys are optional.
#[builder(
start_fn(
name = custom_name,
vis = "pub(crate)",
doc {
/// Custom docs
}
)
)]
name
​
The default name for the starting function is chosen according to the following rules:
Syntax | Default |
---|---|
struct T | builder |
Associated fn T::new() | builder |
Associated fn T::fn_name() | {fn_name} |
Free fn fn_name() | {fn_name} |
vis
​
The visibility must be enclosed with quotes. Use ""
or "pub(self)"
for private visibility.
The default visibility is the same as the visibility of the builder_type
, which in turn, defaults to the visibility of the underlying struct
or fn
.
doc
​
Simple documentation is generated by default. The syntax of this attribute expects a block with doc comments.
doc {
/// Doc comments
}
Examples ​
use bon::Builder;
#[derive(Builder)]
#[builder(start_fn = init)]
struct User {
id: u32
}
User::init()
.id(42)
.build();
use bon::Builder;
// `User::init()` method will have `pub(crate)` visibility
// Use `vis = ""` to make it fully private instead
#[derive(Builder)]
#[builder(start_fn(name = init, vis = "pub(crate)"))]
pub struct User {
id: u32
}
User::init()
.id(42)
.build();
See examples with fn
syntax in the section below.
Exposing original function ​
By default, when you place #[builder]
on a function, that original function is modified by the macro to make it hidden, so that only builder syntax remains available. Specifically, the macro does the following by default:
- Prepends the prefix
__orig_
to the original function's name. - Changes the visibility of the original function to private.
- Adds
#[doc(hidden)]
to the function.
If you specify the start_fn
attribute on a function, the macro skips hiding the original function. It means the starting function no longer replaces the original function. This way both the original positional function and the starting function with the builder syntax are exposed.
This can be used to preserve backwards compatibility for code that uses the original function directly.
NOTE
The name
parameter is required when start_fn
is used with fn
syntax.
Example:
use bon::builder;
#[builder(start_fn = example_builder)]
fn example(x: u32, y: u32) {}
// The original positional function is still available
example(1, 2);
// The builder syntax is also available under the given name
example_builder()
.x(1)
.y(2)
.call();
use bon::bon;
struct Example;
#[bon]
impl Example {
#[builder(start_fn = builder)]
fn new(x: u32, y: u32) -> Self {
Example
}
#[builder(start_fn = method_builder)]
fn method(&self, x: u32, y: u32) {}
}
// The original method `new` is still available
Example::new(1, 2);
// The builder syntax is also available under the given name
let example = Example::builder()
.x(1)
.y(2)
.build();
// The original `method` is still available
example.method(1, 2);
// The builder syntax for the `method` is also available under the given name
example.method_builder()
.x(1)
.y(2)
.call();
One interesting quirk is that by default the associated method named new
already generates a starting function under the name builder
. However, by default, the original method new
also becomes hidden. By specifying the #[builder(start_fn = builder)]
explicitly the original method new
remains exposed.
Given that #[builder(start_fn)]
on a function behaves additively, you can provide builder syntax as an opt-in cargo feature of your crate.
Example:
#[cfg_attr(feature = "bon", bon::builder(start_fn = function_builder))]
fn function() {}
If you use this syntax, the function()
always remains available with or without the bon
feature enabled.