Repository: elastio/bon (Rust)

Issue:
Optional types have to implement default
If I do this:
```rust
struct TestType;

#[builder]
fn test(test_type: Option<TestType>) {}

fn run() {
    test().call();
}
```
I get this error:
```
the method `call` exists for struct `TestBuilder`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`TestType: std::default::Default`
which is required by `bon::private::Optional<viewer::kmp::checkpoints::TestType>: bon::private::IntoSet<std::option::Option<viewer::kmp::checkpoints::TestType>>`
```
Am I missing something? Why do optional types need to implement `Default`?


Discussion:
Interestingly, if you change it to this:
```rust
struct TestType;

#[builder]
fn test(test_type: Option<TestType>) {}

fn run() {
    test().maybe_test_type(None::<TestType>).call();
}
```
the error goes away. If you just do `None` and not `None::<TestType>` there is an error which is strange!
Thank you for the bug report! It's a really small bug in `bon`, I'll fix it shortly and make a patch release, thank you!
The fix has been released in a new patch version `1.0.2`.
Feel free to reopen the issue if the problem persists.

> If you just do `None` and not `None::<TestType>` there is an error which is strange!

This is a bit different problem that is inherent to the setter method signature:
```rust
fn maybe_test_type(self, value: Option<impl Into<TestType>>) -> NextBuilderState
```

Because it accepts an `Option<impl Into<TestType>>` the type of `None` needs to be explicitly specified unless inferred by the compiler from other context.

You can disable the automatic `impl Into` in the setter by adding [`#[builder(into = false)]`](https://elastio.github.io/bon/docs/reference/builder#into) to the field if that is a problem for you. But generally, passing `None` to the optional setter is not needed because you can just omit calling the setter at all.



Patch:
diff --git a/bon-macros/src/lib.rs b/bon-macros/src/lib.rs
index 930da4d1..171b5462 100644
--- a/bon-macros/src/lib.rs
+++ b/bon-macros/src/lib.rs
@@ -48,8 +48,9 @@ pub fn builder(params: TokenStream, item: TokenStream) -> TokenStream {
 }
 
 /// Companion macro for [`builder`]. You should place it on top of the `impl` block
-/// where you want to define methods with the [`builder`] macro. It provides
-/// the necessary context to the [`builder`] macros on top of the functions
+/// where you want to define methods with the [`builder`] macro.
+///
+/// It provides the necessary context to the [`builder`] macros on top of the functions
 /// inside of the `impl` block. You'll get compile errors without that context.
 ///
 /// For details on this macro including the reason why it's needed see this
diff --git a/bon-macros/src/util/ident.rs b/bon-macros/src/util/ident.rs
index 42a64de8..90ac729b 100644
--- a/bon-macros/src/util/ident.rs
+++ b/bon-macros/src/util/ident.rs
@@ -19,8 +19,11 @@ pub(crate) impl syn::Ident {
     /// produced identifier won't influence the syntax highlighting of the original
     /// identifier.
     fn to_pascal_case(&self) -> Self {
-        // There are no pascal case raw identifiers, so no need to handle raw
-        // identifiers here.
+        // There are no pascal case keywords in Rust except for `Self`, which
+        // is anyway not allowed even as a raw identifier:
+        // https://internals.rust-lang.org/t/raw-identifiers-dont-work-for-all-identifiers/9094
+        //
+        // So no need to handle raw identifiers here.
         syn::Ident::new(&self.raw_name().to_pascal_case(), Span::call_site())
     }
 
diff --git a/bon/src/lib.rs b/bon/src/lib.rs
index 70717ac3..752be22c 100644
--- a/bon/src/lib.rs
+++ b/bon/src/lib.rs
@@ -39,8 +39,10 @@ macro_rules! vec {
 }
 
 /// Creates a fixed-size array literal where each element is converted with [`Into::into()`]
-/// into the target type. You'll probably need a hint for the target type of items
-/// in the array if the compiler can't infer it from its usage.
+/// into the target type.
+///
+/// You'll probably need a hint for the target type of items in the array if the
+/// compiler can't infer it from its usage.
 ///
 /// This is similar in spirit to the [`bon::vec!`] macro, but it's for arrays.
 /// See [`bon::vec!`] docs for details.
diff --git a/bon/src/private.rs b/bon/src/private.rs
index f3e34dd6..56c1b838 100644
--- a/bon/src/private.rs
+++ b/bon/src/private.rs
@@ -30,7 +30,7 @@ impl<T> Default for Optional<T> {
     }
 }
 
-impl<T: Default> IntoSet<Option<T>> for Optional<T> {
+impl<T> IntoSet<Option<T>> for Optional<T> {
     fn into_set(self) -> Set<Option<T>> {
         Set::new(None)
     }
diff --git a/website/docs/contributing.md b/website/docs/contributing.md
index 7320fcc8..e349ae02 100644
--- a/website/docs/contributing.md
+++ b/website/docs/contributing.md
@@ -38,8 +38,8 @@ We'll release your change soon after it lands in `master`, or later as part of a
 
 ## License
 
-Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
-2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+Licensed under either of [Apache License, Version
+2.0](https://github.com/elastio/bon/blob/master/LICENSE-APACHE) or [MIT license](https://github.com/elastio/bon/blob/master/LICENSE-MIT) at your option.
 
 Unless you explicitly state otherwise, any contribution intentionally submitted
 for inclusion in the work by you, as defined in the Apache-2.0 license, shall be


Test patch:
diff --git a/bon/tests/integration/builder_on_struct.rs b/bon/tests/integration/builder_on_struct.rs
index 7449fcb1..856d0766 100644
--- a/bon/tests/integration/builder_on_struct.rs
+++ b/bon/tests/integration/builder_on_struct.rs
@@ -89,3 +89,14 @@ fn raw_identifiers() {
 
     let _: r#type = Sut::builder();
 }
+
+// This is based on the issue https://github.com/elastio/bon/issues/12
+#[test]
+fn types_not_implementing_default() {
+    struct DoesNotImplementDefault;
+
+    #[builder]
+    fn test(_value: Option<DoesNotImplementDefault>) {}
+
+    test().call();
+}