Skip to content

Optional Members

Option<T>

If your function argument or struct field (or member for short) is of type Option<T>, then the generated builder will not enforce setting a value for this member, defaulting to None.

rust
#[bon::builder]
fn example(level: Option<u32>) {}

// We can call it without specifying the `level`
example().call();

You can use #[builder(required)] to opt-out from this.

Setters pair

The builder provides a pair of setters for each optional member:

NameInputDescriptionConfiguration attribute
{member}TAccepts a non-None value.some_fn
maybe_{member}Option<T>Accepts an Option directly.option_fn

This is how setters look in the generated code for the example above (simplified):

rust
impl<S> ExampleBuilder<S> {
    fn level(self, value: u32) -> ExampleBuilder<SetLevel<S>> {
        self.maybe_level(Some(value)) // Yes, it's this simple!
    }

    fn maybe_level(self, value: Option<u32>) -> ExampleBuilder<SetLevel<S>> {
        /* */
    }
}

Thanks to this design, changing the member from required to optional preserves compatibility.

Examples

Pass a non-None value via the {member}(T) setter:

rust
example().level(42).call();

Pass an Option value directly via the maybe_{member}(Option<T>) setter:

rust
let value = if some_condition {
    Some(42)
} else {
    None
};

example().maybe_level(value).call();

#[builder(default)]

To make a member of non-Option type optional you may use #[builder(default)]. This attribute uses the Default trait or the provided expression to assign the default value for the member.

TIP

Switching between #[builder(default)] and Option<T> is compatible.

rust
#[bon::builder]
fn example(
    // This uses the `Default` trait
    #[builder(default)]              
    a: u32,

    // This uses the given custom default value
    #[builder(default = 4)]                     
    b: u32,
) -> u32 {
    a + b
}

// Here, the default values will be used `a = 0` and `b = 4`
let result = example().call();

assert_eq!(result, 4);

The same pair of optional setters is generated for members with default values.

rust
let result = example()
    // Pass a non-None value
    .a(3)
    // Pass an `Option` value directly. `None` means the default
    // value will be used (4 in this case)
    .maybe_b(None)
    .call();

You can also reference other members in the default expression. See #[builder(default)] reference for details.

Conditional building

Now that you know how optional members work you can check out the Conditional Building design patterns or continue studying other features of bon by following the "Next page" link at the bottom.