From 454bf6743fdd7f6dd8461330cbc0a2a1d6d0e6a9 Mon Sep 17 00:00:00 2001 From: Veetaha Date: Fri, 8 Nov 2024 03:21:24 +0000 Subject: [PATCH 1/6] Compile time benchmarks --- Cargo.lock | 24 +++++--- Cargo.toml | 3 +- README.v3.md | 8 +++ benchmarks/compilation/results.md | 22 ++++--- benchmarks/compilation/run.sh | 1 - bon-sandbox/Cargo.toml | 35 +++++++++++ {e2e-tests => bon-sandbox}/src/attr_with.rs | 0 bon-sandbox/src/docs_comparison.rs | 59 +++++++++++++++++++ {e2e-tests => bon-sandbox}/src/lib.rs | 21 +++---- .../src/macro_rules_wrapper_test.rs | 0 .../src/missing_docs_test.rs | 0 {e2e-tests => bon-sandbox}/src/reexports.rs | 0 .../src/state_mod_pub.rs | 0 website/.vitepress/config.mts | 2 +- website/.vitepress/theme/utils/versioning.ts | 4 +- website/doctests/Cargo.toml | 25 ++++++++ {e2e-tests => website/doctests}/build.rs | 6 +- website/doctests/src/lib.rs | 10 ++++ website/src/guide/alternatives.md | 8 ++- website/src/guide/benchmarks/compilation.md | 56 ++++++++++++++++++ website/src/reference/builder.md | 4 -- 21 files changed, 242 insertions(+), 46 deletions(-) create mode 100644 bon-sandbox/Cargo.toml rename {e2e-tests => bon-sandbox}/src/attr_with.rs (100%) create mode 100644 bon-sandbox/src/docs_comparison.rs rename {e2e-tests => bon-sandbox}/src/lib.rs (88%) rename {e2e-tests => bon-sandbox}/src/macro_rules_wrapper_test.rs (100%) rename {e2e-tests => bon-sandbox}/src/missing_docs_test.rs (100%) rename {e2e-tests => bon-sandbox}/src/reexports.rs (100%) rename {e2e-tests => bon-sandbox}/src/state_mod_pub.rs (100%) create mode 100644 website/doctests/Cargo.toml rename {e2e-tests => website/doctests}/build.rs (93%) create mode 100644 website/doctests/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 3830ef5b..138c6a83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,16 @@ dependencies = [ "syn", ] +[[package]] +name = "bon-sandbox" +version = "2.3.0" +dependencies = [ + "bon", + "buildstructor", + "derive_builder", + "typed-builder", +] + [[package]] name = "borsh" version = "1.5.1" @@ -395,13 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" [[package]] -name = "drop_bomb" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" - -[[package]] -name = "e2e-tests" +name = "doctests" version = "0.1.0" dependencies = [ "anyhow", @@ -413,6 +417,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "drop_bomb" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" + [[package]] name = "either" version = "1.13.0" diff --git a/Cargo.toml b/Cargo.toml index b6e4bd1a..ed864851 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ members = [ "bon", "bon-cli", "bon-macros", - "e2e-tests", + "bon-sandbox", + "website/doctests", ] resolver = "2" diff --git a/README.v3.md b/README.v3.md index 0f9cba6b..9df8f043 100644 --- a/README.v3.md +++ b/README.v3.md @@ -206,6 +206,14 @@ This project was heavily inspired by such awesome crates as [`buildstructor`](ht See [alternatives](https://bon-rs.com/guide/alternatives) for comparison. +## Who's Using `bon`? + +- [`crates.io` backend](https://github.com/rust-lang/crates.io) +- [`ractor`](https://github.com/slawlor/ractor) +- [`comrak`](https://github.com/kivikakk/comrak) +- [`soldeer`](https://github.com/mario-eth/soldeer) (package manager endorsed by [`foundry`](https://github.com/foundry-rs/foundry)) +- [`tachyonfx`](https://github.com/junkdog/tachyonfx) + ## Getting Help If you can't figure something out, consult the docs and maybe use the `🔍 Search` bar on our [docs website](https://bon-rs.com). You may also create an issue or a discussion on the [Github repository](https://github.com/elastio/bon) for help or write us a message on [Discord](https://bon-rs.com/discord). diff --git a/benchmarks/compilation/results.md b/benchmarks/compilation/results.md index 5af1cb01..5217a0e9 100644 --- a/benchmarks/compilation/results.md +++ b/benchmarks/compilation/results.md @@ -1,12 +1,10 @@ -| Command | Mean [s] | Min [s] | Max [s] | Relative | -| :--------------------------------------- | ------------: | ------: | ------: | -----------: | -| `structs_100_fields_10 bon` | 2.319 ± 0.021 | 2.278 | 2.350 | 22.80 ± 2.99 | -| `structs_100_fields_10 bon-overwritable` | 2.240 ± 0.021 | 2.203 | 2.274 | 22.03 ± 2.89 | -| `structs_100_fields_10 typed-builder` | 1.849 ± 0.011 | 1.838 | 1.878 | 18.18 ± 2.38 | -| `structs_100_fields_10 derive_builder` | 1.022 ± 0.016 | 0.995 | 1.043 | 10.05 ± 1.32 | -| `structs_100_fields_10 ` | 0.104 ± 0.012 | 0.088 | 0.124 | 1.02 ± 0.18 | -| `structs_10_fields_50 bon` | 2.063 ± 0.017 | 2.044 | 2.100 | 20.28 ± 2.66 | -| `structs_10_fields_50 bon-overwritable` | 2.029 ± 0.029 | 1.998 | 2.102 | 19.95 ± 2.62 | -| `structs_10_fields_50 typed-builder` | 2.076 ± 0.016 | 2.048 | 2.101 | 20.41 ± 2.67 | -| `structs_10_fields_50 derive_builder` | 0.432 ± 0.016 | 0.400 | 0.458 | 4.25 ± 0.58 | -| `structs_10_fields_50 ` | 0.102 ± 0.013 | 0.084 | 0.130 | 1.00 | +| Command | Mean [s] | Min [s] | Max [s] | Relative | +| :------------------------------------- | ------------: | ------: | ------: | -----------: | +| `structs_100_fields_10 bon` | 2.340 ± 0.019 | 2.315 | 2.364 | 20.86 ± 1.37 | +| `structs_100_fields_10 typed-builder` | 1.831 ± 0.015 | 1.806 | 1.859 | 16.32 ± 1.07 | +| `structs_100_fields_10 derive_builder` | 1.026 ± 0.013 | 1.009 | 1.048 | 9.14 ± 0.61 | +| `structs_100_fields_10 ` | 0.113 ± 0.010 | 0.092 | 0.125 | 1.01 ± 0.11 | +| `structs_10_fields_50 bon` | 2.096 ± 0.009 | 2.080 | 2.109 | 18.69 ± 1.22 | +| `structs_10_fields_50 typed-builder` | 2.088 ± 0.014 | 2.067 | 2.115 | 18.61 ± 1.22 | +| `structs_10_fields_50 derive_builder` | 0.449 ± 0.022 | 0.391 | 0.470 | 4.00 ± 0.33 | +| `structs_10_fields_50 ` | 0.112 ± 0.007 | 0.086 | 0.116 | 1.00 | diff --git a/benchmarks/compilation/run.sh b/benchmarks/compilation/run.sh index 74d5dc8d..2d72a764 100755 --- a/benchmarks/compilation/run.sh +++ b/benchmarks/compilation/run.sh @@ -4,7 +4,6 @@ set -euxo pipefail macros=( bon - bon-overwritable typed-builder derive_builder ) diff --git a/bon-sandbox/Cargo.toml b/bon-sandbox/Cargo.toml new file mode 100644 index 00000000..4dd3c2ab --- /dev/null +++ b/bon-sandbox/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "bon-sandbox" +version = "2.3.0" + +description = """ + Not a real crate! It's just a showcase of examples used by `bon`'s documentation + to demonstrate the rustdoc output for code generated by builder macros. + + Don't use this crate, it doesn't follow semver at all and serves no other puprose + other than linking to its docs as an example! +""" + +edition = "2021" +homepage = "https://bon-rs.com" +license = "MIT OR Apache-2.0" +repository = "https://github.com/elastio/bon" + +[package.metadata.docs.rs] +all-features = true + +# Generate clickable links in the source code view in the docs +rustdoc-args = ["--generate-link-to-definition"] + +# We don't need the docs to be built for every first-tier target. +# This crate is not platform-specific. +targets = ["x86_64-unknown-linux-gnu"] + +[lints] +workspace = true + +[dependencies] +bon = { path = "../bon", version = "=2.3.0" } +buildstructor = "0.5" +derive_builder = "0.20" +typed-builder = "0.20" diff --git a/e2e-tests/src/attr_with.rs b/bon-sandbox/src/attr_with.rs similarity index 100% rename from e2e-tests/src/attr_with.rs rename to bon-sandbox/src/attr_with.rs diff --git a/bon-sandbox/src/docs_comparison.rs b/bon-sandbox/src/docs_comparison.rs new file mode 100644 index 00000000..55edf35d --- /dev/null +++ b/bon-sandbox/src/docs_comparison.rs @@ -0,0 +1,59 @@ +#![allow(dead_code)] + +pub mod bon { + #[derive(bon::Builder)] + pub struct Example { + x1: u32, + + #[builder(default = 2 + 2)] + x2: u32, + + x3: Option, + + #[builder(into)] + x4: String, + } +} + +pub mod buildstructor { + #[derive(buildstructor::Builder)] + pub struct Example { + x1: u32, + x2: u32, + x3: Option, + x4: String, + } +} + +pub mod typed_builder { + #[derive(typed_builder::TypedBuilder)] + #[builder(doc)] + pub struct Example { + x1: u32, + + #[builder(default = 2 + 2)] + x2: u32, + + #[builder(default)] + x3: Option, + + #[builder(setter(into))] + x4: String, + } +} + +pub mod derive_builder { + #[derive(derive_builder::Builder)] + pub struct Example { + x1: u32, + + #[builder(default = 2 + 2)] + x2: u32, + + #[builder(default)] + x3: Option, + + #[builder(setter(into))] + x4: String, + } +} diff --git a/e2e-tests/src/lib.rs b/bon-sandbox/src/lib.rs similarity index 88% rename from e2e-tests/src/lib.rs rename to bon-sandbox/src/lib.rs index f5f263a1..93802daa 100644 --- a/e2e-tests/src/lib.rs +++ b/bon-sandbox/src/lib.rs @@ -1,8 +1,12 @@ -//! This crate is used only for testing of the public interface of the `bon` crate. -//! We don't need all the aggressive lints that we use for public crates. +//! Not a real crate! It's just a showcase of examples used by `bon`'s documentation +//! to demonstrate the rustdoc output for code generated by builder macros. +//! +//! Don't use this crate, it doesn't follow semver at all and serves no other puprose +//! other than linking to its docs as an example! #![allow(missing_debug_implementations, missing_docs)] pub mod attr_with; +pub mod docs_comparison; pub mod macro_rules_wrapper_test; pub mod missing_docs_test; pub mod state_mod_pub; @@ -13,15 +17,6 @@ pub use reexports::{UnexportedBuilder, UnexportedStateMod, UnexportedStateModBui use bon::{bon, builder, Builder}; -#[cfg(doctest)] -// We use a bunch of Vitepress-specific syntax in the doctests, for example to -// give a name to a code group in a fenced code block, which conflicts with this -// lint. -#[deny(rustdoc::invalid_codeblock_attributes)] -mod website_doctests { - include!(concat!(env!("OUT_DIR"), "/website_doctests.rs")); -} - /// Some docs on the private builder #[derive(Builder)] #[builder(builder_type(vis = ""))] @@ -131,13 +126,13 @@ pub fn documented( } /// Function that returns a greeting special-tailored for a given person -#[builder(builder_type = Foo)] +#[builder(builder_type = GreeterBuilderCustom)] pub fn greet( /// Name of the person to greet. /// /// **Example:** /// ``` - /// e2e_tests::greet().name("John"); + /// bon_sandbox::greet().name("John"); /// ``` name: &str, diff --git a/e2e-tests/src/macro_rules_wrapper_test.rs b/bon-sandbox/src/macro_rules_wrapper_test.rs similarity index 100% rename from e2e-tests/src/macro_rules_wrapper_test.rs rename to bon-sandbox/src/macro_rules_wrapper_test.rs diff --git a/e2e-tests/src/missing_docs_test.rs b/bon-sandbox/src/missing_docs_test.rs similarity index 100% rename from e2e-tests/src/missing_docs_test.rs rename to bon-sandbox/src/missing_docs_test.rs diff --git a/e2e-tests/src/reexports.rs b/bon-sandbox/src/reexports.rs similarity index 100% rename from e2e-tests/src/reexports.rs rename to bon-sandbox/src/reexports.rs diff --git a/e2e-tests/src/state_mod_pub.rs b/bon-sandbox/src/state_mod_pub.rs similarity index 100% rename from e2e-tests/src/state_mod_pub.rs rename to bon-sandbox/src/state_mod_pub.rs diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts index 4ee795a3..c467320f 100644 --- a/website/.vitepress/config.mts +++ b/website/.vitepress/config.mts @@ -81,7 +81,7 @@ export default defineConfig({ }, }, - srcExclude: ["README.md", "infra/**"], + srcExclude: ["README.md", "infra/**", "doctests/**"], head, diff --git a/website/.vitepress/theme/utils/versioning.ts b/website/.vitepress/theme/utils/versioning.ts index 5847de3d..3116d1aa 100644 --- a/website/.vitepress/theme/utils/versioning.ts +++ b/website/.vitepress/theme/utils/versioning.ts @@ -1,7 +1,7 @@ import { withBase } from "vitepress"; -export const latestVersion = "v3-rc"; -export const versions = ["v3-rc", "v2", "v1"]; +export const latestVersion = "v3"; +export const versions = ["v3", "v2", "v1"]; export const sectionRoots = { guide: "guide/overview", diff --git a/website/doctests/Cargo.toml b/website/doctests/Cargo.toml new file mode 100644 index 00000000..9c790ebb --- /dev/null +++ b/website/doctests/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "doctests" +version = "0.1.0" + +publish = false + +description = "Crate for testing Rust code snippets in the markdown files on the website." + +edition = "2021" + +[lints] +workspace = true + +[dependencies] +bon = { path = "../../bon", features = ["experimental-overwritable"] } + +[dev-dependencies] +anyhow = "1.0" +buildstructor = "0.5" +macro_rules_attribute = "0.2" + +[build-dependencies] +itertools = "0.13" +lazy-regex = "3.3" +walkdir = "2.5" diff --git a/e2e-tests/build.rs b/website/doctests/build.rs similarity index 93% rename from e2e-tests/build.rs rename to website/doctests/build.rs index 1e7a3144..9cb1aac8 100644 --- a/e2e-tests/build.rs +++ b/website/doctests/build.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use walkdir::DirEntry; fn main() { - let website = "../website"; + let website = ".."; println!("cargo::rerun-if-changed={website}"); @@ -22,8 +22,8 @@ fn main() { .filter(|entry| { entry.file_type().is_file() && entry.path().extension() == Some("md".as_ref()) - && !entry.path().starts_with("../website/src/v1") - && !entry.path().starts_with("../website/src/v2") + && !entry.path().starts_with("../src/v1") + && !entry.path().starts_with("../src/v2") }) .map(DirEntry::into_path) .sorted_unstable() diff --git a/website/doctests/src/lib.rs b/website/doctests/src/lib.rs new file mode 100644 index 00000000..ee400c52 --- /dev/null +++ b/website/doctests/src/lib.rs @@ -0,0 +1,10 @@ +//! Crate for testing Rust code snippets in the markdown files on the website. + +#[cfg(doctest)] +// We use a bunch of Vitepress-specific syntax in the doctests, for example to +// give a name to a code group in a fenced code block, which conflicts with this +// lint. +#[deny(rustdoc::invalid_codeblock_attributes)] +mod website_doctests { + include!(concat!(env!("OUT_DIR"), "/website_doctests.rs")); +} diff --git a/website/src/guide/alternatives.md b/website/src/guide/alternatives.md index 4c08ae50..1c4e3f0b 100644 --- a/website/src/guide/alternatives.md +++ b/website/src/guide/alternatives.md @@ -20,7 +20,7 @@ There are several other existing alternative crates for generating builders. `bo | ---------------------------------------- | ---------------------------------- | ------------------------- | ----------------------- | --------------------------------------------- | | Builder for structs | ✅ | ✅ | ✅ | ✅ | | Builder for functions | ✅ | | | -| Builder for associated methods | ✅ | ✅ | | +| Builder for methods | ✅ | ✅ | | | Panic safe | ✅ | ✅ | ✅ | `build()` returns `Result` | | `Option` makes members optional | ✅ | ✅ | | | | `T` -> `Option` is non-breaking | ✅ [docs][bon-req-to-opt] | ✅ | via attr `strip_option` | via attr [`strip_option`][db-so] | @@ -151,7 +151,11 @@ Moreover, it offers you a completely new dimension of flexibility: The chances of hitting a wall with function builders are close to zero, and even if you ever do, you still have access to the [Typestate API](./typestate-api) in `bon` for even more flexibility 💪. -## Special setter methods for collections +## Documentation Comparison + +You can compare the `rustdoc` output for builders generated by different crates. See the source code for this comparison [here]. + +## Special Setter Methods for Collections Other builder crates provide a way to generate methods to build collections one element at a time. For example, `buildstructor` even generates such methods by default: diff --git a/website/src/guide/benchmarks/compilation.md b/website/src/guide/benchmarks/compilation.md index e69de29b..64bc60ae 100644 --- a/website/src/guide/benchmarks/compilation.md +++ b/website/src/guide/benchmarks/compilation.md @@ -0,0 +1,56 @@ +# Compilation Benchmarks + +This page describes the results of benchmarking the performance of compiling code generated by `bon`'s and other alternative crates' builder macros. + +There are two things contributing to compile times: + +1. Compiling the proc macro crate into a dynamic library. +2. Compiling the code generated by the proc macros. + +The benchmarks here intentionally exclude `1` from measurements. This is because the proc macro crate itself compiles blazingly fast ⚡. For example, once you add `bon` as a dependency, its will compiled only once and never recompiled during incremental rebuilds. + +## Measurements + +The benchmarks measure the time it takes to run `cargo build` against a crate that uses `#[derive(Builder)]` for the given number of structs with the given number of fields in each of them. + +### 100 structs with 10 fields + +| Builder crate | Compile time | +| ---------------- | ------------ | +| `bon` | `2.340s` | +| `typed-builder` | `1.831s` | +| `derive_builder` | `1.026s` | +| no macros | `0.113s` | + +### 10 structs with 50 fields + +| Builder crate | Compile time | +| ---------------- | ------------ | +| `bon` | `2.096s` | +| `typed-builder` | `2.088s` | +| `derive_builder` | `0.449s` | +| no macros | `0.112s` | + +## Summary + +As you can see the code generated by `bon` takes more time to compile than with other builder crates. It is close to `typed-builder` in the [second](#10-structs-with-50-fields) benchmark though. + +Now don't rush to conclusions ✋. To be fair, the amount of features and improvements `bon` provides over other crates is worth the slightly higher compilation time. The difference isn't that critical with the number of structs/fields used in the measurements here. + +However, let's address some questions. + +### Why `derive_builder` is fastest to compile? + +The main contributor to compile times of code generated by `bon` and `typed-builder` is their usage of generics to represent the type state. The builders generated by `derive_builder` don't use any generics. + +The main downside of `derive_builder`'s approach is that its finishing `build()` method always returns a `Result`, because it needs to validate, that all required fields were set **at runtime**. + +### Why `bon` loses to `typed-builder` in compilation perf? + +`bon`'s generated code is a bit more complex than `typed-builder`'s, because `bon` generates additional traits and types to expose a nice and stable [typestate API](../typestate-api). + +This is also done to reduce the builder's type signature size and reduce the noisy generic in the documentation generated by `rustdoc`. In fact, the difference in the generated docs between `bon` and `typed-builder` is [drastic](../alternatives#documentation-comparison). + +### Can `bon` do better for compile times? + +Unfortunately, it's a tradeoff. diff --git a/website/src/reference/builder.md b/website/src/reference/builder.md index d6b97bb1..6e80c76f 100644 --- a/website/src/reference/builder.md +++ b/website/src/reference/builder.md @@ -2,10 +2,6 @@ outline: deep --- -# `#[derive(Builder)]` / `#[builder]` - -Generate builders from structs via `#[derive(Builder)]`, free functions via `#[builder]`, and associated methods via `#[bon]` + `#[builder]`. They all use the same attributes syntax. - ## Top-Level Attributes These attributes are placed on top of a `struct` or `fn` declaration. From e93d3ec31dd2df65b10624ad431d754225a3c76e Mon Sep 17 00:00:00 2001 From: Veetaha Date: Fri, 8 Nov 2024 03:21:24 +0000 Subject: [PATCH 2/6] Compilation benchmarks --- .../src/builder/builder_gen/setters/mod.rs | 30 ++- bon-sandbox/src/attr_default.rs | 30 +++ bon-sandbox/src/docs_comparison.rs | 59 ------ bon-sandbox/src/docs_comparison/functions.rs | 21 ++ bon-sandbox/src/docs_comparison/methods.rs | 44 +++++ bon-sandbox/src/docs_comparison/mod.rs | 27 +++ bon-sandbox/src/docs_comparison/structs.rs | 85 ++++++++ bon-sandbox/src/functions.rs | 120 ++++++++++++ bon-sandbox/src/lib.rs | 181 +----------------- bon-sandbox/src/overrides.rs | 34 ++++ bon-sandbox/src/private_builder.rs | 6 + .../src/state_mod}/comprehensive.rs | 32 +++- .../src/state_mod}/minimal.rs | 4 +- bon-sandbox/src/state_mod/mod.rs | 4 + bon-sandbox/src/state_mod_pub.rs | 25 --- bon/src/examples/mod.rs | 2 - bon/src/lib.rs | 4 - website/src/guide/alternatives.md | 38 +++- website/src/guide/benchmarks/compilation.md | 77 +++++--- website/src/guide/benchmarks/runtime.md | 2 +- website/src/index.md | 3 + .../src/reference/builder/member/default.md | 10 +- 22 files changed, 505 insertions(+), 333 deletions(-) create mode 100644 bon-sandbox/src/attr_default.rs delete mode 100644 bon-sandbox/src/docs_comparison.rs create mode 100644 bon-sandbox/src/docs_comparison/functions.rs create mode 100644 bon-sandbox/src/docs_comparison/methods.rs create mode 100644 bon-sandbox/src/docs_comparison/mod.rs create mode 100644 bon-sandbox/src/docs_comparison/structs.rs create mode 100644 bon-sandbox/src/functions.rs create mode 100644 bon-sandbox/src/overrides.rs create mode 100644 bon-sandbox/src/private_builder.rs rename {bon/src/examples => bon-sandbox/src/state_mod}/comprehensive.rs (57%) rename {bon/src/examples => bon-sandbox/src/state_mod}/minimal.rs (83%) create mode 100644 bon-sandbox/src/state_mod/mod.rs delete mode 100644 bon-sandbox/src/state_mod_pub.rs delete mode 100644 bon/src/examples/mod.rs diff --git a/bon-macros/src/builder/builder_gen/setters/mod.rs b/bon-macros/src/builder/builder_gen/setters/mod.rs index 1b4592ab..db310c15 100644 --- a/bon-macros/src/builder/builder_gen/setters/mod.rs +++ b/bon-macros/src/builder/builder_gen/setters/mod.rs @@ -499,9 +499,7 @@ impl SettersItems { if member.is_required() { let docs = common_docs.unwrap_or(&member.docs); - let header = "\ - | **Required** |\n\ - | -- |\n\n"; + let header = "_**Required.**_\n\n"; let docs = doc(header).chain(docs.iter().cloned()).collect(); @@ -560,8 +558,10 @@ impl SettersItems { .or(common_docs) .unwrap_or(&member.docs); + let setter_names = (&some_fn_name, &option_fn_name); + let some_fn_docs = { - let header = optional_setter_docs(default, &option_fn_name, "accepts an `Option`"); + let header = optional_setter_docs(default, setter_names); doc(&header).chain(some_fn_docs.iter().cloned()).collect() }; @@ -572,11 +572,7 @@ impl SettersItems { .unwrap_or(&member.docs); let option_fn_docs = { - let header = optional_setter_docs( - default, - &some_fn_name, - "wraps the value with `Some` internally", - ); + let header = optional_setter_docs(default, setter_names); doc(&header).chain(option_fn_docs.iter().cloned()).collect() }; @@ -611,25 +607,21 @@ impl SettersItems { fn optional_setter_docs( default: Option<&str>, - other_setter: &syn::Ident, - description: &str, + (some_fn, option_fn): (&syn::Ident, &syn::Ident), ) -> String { let default = default .map(|default| { if default.contains('\n') || default.len() > 80 { - format!("**Default:**\n````rust,ignore\n{default}\n````\n\n") + format!(" _**Default:**_\n````rust,ignore\n{default}\n````\n\n") } else { - format!("**Default:** ```{default}```.\n\n") + format!(" _**Default:**_ ```{default}```.\n\n") } }) .unwrap_or_default(); - format!( - "| **Optional** |\n\ - | -- |\n\n\ - **See also** [`{other_setter}()`](Self::{other_setter}), which is a companion setter that {description}. - \n\n{default}", - ) + let setters = format!(" [Some](Self::{some_fn}()) / [Option](Self::{option_fn}()) setters"); + + format!("_**Optional** ({setters})._{default}\n\n",) } fn well_known_default(ty: &syn::Type) -> Option { diff --git a/bon-sandbox/src/attr_default.rs b/bon-sandbox/src/attr_default.rs new file mode 100644 index 00000000..a43d9cf5 --- /dev/null +++ b/bon-sandbox/src/attr_default.rs @@ -0,0 +1,30 @@ +#[derive(bon::Builder)] +#[builder(builder_type( + doc { + /// Showcases examples of `#[builder(default)]` usage and what docs are + /// generated for them. Click on any of `source` links to see the source code. + } +))] +pub struct Example { + #[builder(default = (2 + 2) * 10)] + small_custom_default: u32, + + #[builder(default = Vec::from([ + Point { x: 1, y: 2 }, + Point { x: 3, y: 4 }, + Point { x: 5, y: 6 }, + Point { x: 7, y: 8 }, + ]))] + big_custom_default: Vec, + + #[builder(default)] + standard_u32_default: u32, + + #[builder(default)] + standard_string_default: String, +} + +struct Point { + x: u32, + y: u32, +} diff --git a/bon-sandbox/src/docs_comparison.rs b/bon-sandbox/src/docs_comparison.rs deleted file mode 100644 index 55edf35d..00000000 --- a/bon-sandbox/src/docs_comparison.rs +++ /dev/null @@ -1,59 +0,0 @@ -#![allow(dead_code)] - -pub mod bon { - #[derive(bon::Builder)] - pub struct Example { - x1: u32, - - #[builder(default = 2 + 2)] - x2: u32, - - x3: Option, - - #[builder(into)] - x4: String, - } -} - -pub mod buildstructor { - #[derive(buildstructor::Builder)] - pub struct Example { - x1: u32, - x2: u32, - x3: Option, - x4: String, - } -} - -pub mod typed_builder { - #[derive(typed_builder::TypedBuilder)] - #[builder(doc)] - pub struct Example { - x1: u32, - - #[builder(default = 2 + 2)] - x2: u32, - - #[builder(default)] - x3: Option, - - #[builder(setter(into))] - x4: String, - } -} - -pub mod derive_builder { - #[derive(derive_builder::Builder)] - pub struct Example { - x1: u32, - - #[builder(default = 2 + 2)] - x2: u32, - - #[builder(default)] - x3: Option, - - #[builder(setter(into))] - x4: String, - } -} diff --git a/bon-sandbox/src/docs_comparison/functions.rs b/bon-sandbox/src/docs_comparison/functions.rs new file mode 100644 index 00000000..3fb3f4fd --- /dev/null +++ b/bon-sandbox/src/docs_comparison/functions.rs @@ -0,0 +1,21 @@ +/// Example docs generated with `bon` +pub mod bon { + /// Doc comment on `function` + #[bon::builder] + pub fn function( + /// Doc comment on `x1` + x1: u32, + + /// Doc comment on `x2` + #[builder(default = 2 + 2)] + x2: u32, + + /// Doc comment on `x3` + x3: Option, + + /// Doc comment on `x4` + #[builder(into)] + x4: String, + ) { + } +} diff --git a/bon-sandbox/src/docs_comparison/methods.rs b/bon-sandbox/src/docs_comparison/methods.rs new file mode 100644 index 00000000..1c68c7af --- /dev/null +++ b/bon-sandbox/src/docs_comparison/methods.rs @@ -0,0 +1,44 @@ +/// Example docs generated with `bon` +pub mod bon { + /// Doc comment on `Struct` + pub struct Struct; + + #[bon::bon] + impl Struct { + /// Doc comment on `method` + #[builder] + pub fn method( + &self, + + /// Doc comment on `x1` + x1: u32, + + /// Doc comment on `x2` + #[builder(default = 2 + 2)] + x2: u32, + + /// Doc comment on `x3` + x3: Option, + + /// Doc comment on `x4` + #[builder(into)] + x4: String, + ) { + } + } +} + +/// Example docs generated with `buildstructor` +#[expect(elided_lifetimes_in_paths)] +pub mod buildstructor { + + /// Doc comment on `Struct` + pub struct Struct; + + #[buildstructor::buildstructor] + impl Struct { + /// Doc comment on `method_orig` + #[builder(entry = "method")] + pub fn method_orig(&self, x1: u32, x2: u32, x3: Option, x4: String) {} + } +} diff --git a/bon-sandbox/src/docs_comparison/mod.rs b/bon-sandbox/src/docs_comparison/mod.rs new file mode 100644 index 00000000..bc480aad --- /dev/null +++ b/bon-sandbox/src/docs_comparison/mod.rs @@ -0,0 +1,27 @@ +//! This module contains examples of `rustdoc` output for builder macros from different +//! crates applied to different kinds of syntax. +//! +//! The module hierarchy here is `syntax` -> `builder_crate`. +//! +//! All builders were configured to produce roughly similar builder API. +//! +//! The notable exceptions are: +//! +//! - `buildstructor` doesn't support `#[builder(default)]` and `#[builder(into)]`-like annotations; +//! - `buildstructor` doesn't support doc comments on function arguments; +//! - `derive_builder` doesn't support typestate-based builders; +#![expect( + dead_code, + unused_variables, + clippy::needless_pass_by_value, + clippy::unused_self +)] + +/// Examples docs generated with builder macros applied to functions +pub mod functions; + +/// Examples docs generated with builder macros applied to structs +pub mod structs; + +/// Examples docs generated with builder macros applied to methods +pub mod methods; diff --git a/bon-sandbox/src/docs_comparison/structs.rs b/bon-sandbox/src/docs_comparison/structs.rs new file mode 100644 index 00000000..342876f9 --- /dev/null +++ b/bon-sandbox/src/docs_comparison/structs.rs @@ -0,0 +1,85 @@ +/// Example docs generated with `bon` +pub mod bon { + /// Doc comment on `Struct` + #[derive(bon::Builder)] + pub struct Struct { + /// Doc comment on `x1` + x1: u32, + + /// Doc comment on `x2` + #[builder(default = 2 + 2)] + x2: u32, + + /// Doc comment on `x3` + x3: Option, + + /// Doc comment on `x4` + #[builder(into)] + x4: String, + } +} + +/// Example docs generated with `buildstructor` +pub mod buildstructor { + /// Doc comment on `Struct` + #[derive(buildstructor::Builder)] + pub struct Struct { + /// Doc comment on `x1` + x1: u32, + + /// Doc comment on `x2` + x2: u32, + + /// Doc comment on `x3` + x3: Option, + + /// Doc comment on `x4` + x4: String, + } +} + +/// Example docs generated with `typed-builder` +pub mod typed_builder { + + /// Doc comment on `Struct` + #[derive(typed_builder::TypedBuilder)] + #[builder(doc)] + pub struct Struct { + /// Doc comment on `x1` + x1: u32, + + /// Doc comment on `x2` + #[builder(default = 2 + 2)] + x2: u32, + + /// Doc comment on `x3` + #[builder(default)] + x3: Option, + + /// Doc comment on `x4` + #[builder(setter(into))] + x4: String, + } +} + +/// Example docs generated with `derive_builder` +pub mod derive_builder { + /// Doc comment on `Struct` + #[derive(derive_builder::Builder)] + pub struct Struct { + /// Doc comment on `x1` + x1: u32, + + /// Doc comment on `x2` + #[builder(default = 2 + 2)] + x2: u32, + + /// Doc comment on `x3` + #[builder(default)] + x3: Option, + + /// Doc comment on `x4` + #[builder(setter(into))] + x4: String, + } +} diff --git a/bon-sandbox/src/functions.rs b/bon-sandbox/src/functions.rs new file mode 100644 index 00000000..3dc2d396 --- /dev/null +++ b/bon-sandbox/src/functions.rs @@ -0,0 +1,120 @@ +use bon::{bon, builder}; + +pub struct Counter { + val: usize, +} + +#[bon] +impl Counter { + #[builder] + pub fn new( + /// Initial value for the counter. + /// If not specified, defaults to 0. + #[builder(default)] + initial: usize, + ) -> Self { + eprintln!("Non-const"); + Self { val: initial } + } + + /// Increments the counter by `diff` amount. If not specified, increments by 1. + #[builder] + pub fn increment( + &mut self, + /// Amount to increment the counter by in [`Counter`]. + diff: Option, + ) { + eprintln!("Non-const"); + self.val += diff.unwrap_or(1); + } +} + +/// Function-level documentation. +#[builder] +#[allow(clippy::needless_pass_by_value)] +pub fn documented( + /// Some documentation for the first argument + /// + /// # Doc test here + /// + /// ``` + /// // Some doc tests as well + /// assert_eq!(2 + 2, 4); + /// ``` + #[builder(default)] + _arg1: String, + + _arg2: &str, + + /// Optional member docs + _arg3: Option, + + _arg4: Vec, + + #[builder(default = vec![1, 2, 3])] _arg5: Vec, +) { + eprintln!("Non-const"); +} + +/// Function that returns a greeting special-tailored for a given person +#[builder(builder_type = GreeterBuilderCustom)] +pub fn greet( + /// Name of the person to greet. + /// + /// **Example:** + /// ``` + /// bon_sandbox::greet().name("John"); + /// ``` + name: &str, + + /// Age expressed in full years passed since the birth date. + age: u32, +) -> String { + eprintln!("Non-const"); + format!("Hello {name} with age {age}!") +} + +#[builder] +pub fn fn_with_impl_trait(_arg1: impl std::fmt::Debug + Clone, _arg2: impl std::fmt::Debug) {} + +#[builder] +pub fn many_function_parameters( + _id: Option<&str>, + _keyword: Option<&str>, + _attraction_id: Option<&str>, + _venue_id: Option<&str>, + _postal_code: Option<&str>, + _latlong: Option<&str>, + _radius: Option<&str>, + _unit: Option<&str>, + _source: Option<&str>, + _locale: Option<&str>, + _market_id: Option<&str>, + _start_date_time: Option<&str>, + _end_date_time: Option<&str>, + _include_tba: Option<&str>, + _include_tbd: Option<&str>, + _include_test: Option<&str>, + _size: Option<&str>, + _page: Option<&str>, + _sort: Option<&str>, + _onsale_start_date_time: Option<&str>, + _onsale_end_date_time: Option<&str>, + _city: Option<&str>, + _country_code: Option<&str>, + _state_code: Option<&str>, + _classification_name: Option<&str>, + _classification_id: Option<&str>, + _dma_id: Option<&str>, + _onsale_on_start_date: Option<&str>, + _onsale_on_after_start_date: Option<&str>, + _segment_id: Option<&str>, + _segment_name: Option<&str>, + _promoter_id: Option<&str>, + _client_visibility: Option<&str>, + _nlp: Option<&str>, + _include_licensed_content: Option<&str>, + _geopoint: Option<&str>, +) { + eprintln!("Non-const"); +} diff --git a/bon-sandbox/src/lib.rs b/bon-sandbox/src/lib.rs index 93802daa..a2385463 100644 --- a/bon-sandbox/src/lib.rs +++ b/bon-sandbox/src/lib.rs @@ -3,187 +3,18 @@ //! //! Don't use this crate, it doesn't follow semver at all and serves no other puprose //! other than linking to its docs as an example! -#![allow(missing_debug_implementations, missing_docs)] +#![allow(missing_debug_implementations, missing_docs, dead_code)] +pub mod attr_default; pub mod attr_with; pub mod docs_comparison; +pub mod functions; pub mod macro_rules_wrapper_test; pub mod missing_docs_test; -pub mod state_mod_pub; +pub mod overrides; +pub mod private_builder; +pub mod state_mod; mod reexports; pub use reexports::{UnexportedBuilder, UnexportedStateMod, UnexportedStateModBuilder}; - -use bon::{bon, builder, Builder}; - -/// Some docs on the private builder -#[derive(Builder)] -#[builder(builder_type(vis = ""))] -pub struct PrivateBuilder { - _field: String, -} - -/// Docs on the [`Self`] struct -#[derive(Builder)] -#[builder( - builder_type( - doc { - /// Docs on [`GreeterOverriddenBuilder`] - /// the builder type - }, - name = GreeterOverriddenBuilder, - ), - start_fn( - doc { - /// Docs on - /// [`Self::start_fn_override`] - }, - name = start_fn_override, - ), - finish_fn( - doc { - /// Docs on - /// [`GreeterOverriddenBuilder::finish_fn_override()`] - }, - name = finish_fn_override, - ) -)] -pub struct Greeter { - /// Docs on - /// the `name` field - _name: String, - - /// Docs on - /// the `level` field - _level: usize, -} - -pub struct Counter { - val: usize, -} - -#[bon] -impl Counter { - #[builder] - pub fn new( - /// Initial value for the counter. - /// If not specified, defaults to 0. - #[builder(default)] - initial: usize, - ) -> Self { - eprintln!("Non-const"); - Self { val: initial } - } - - /// Increments the counter by `diff` amount. If not specified, increments by 1. - #[builder] - pub fn increment( - &mut self, - /// Amount to increment the counter by in [`Counter`]. - diff: Option, - ) { - eprintln!("Non-const"); - self.val += diff.unwrap_or(1); - } -} - -/// Function-level documentation. -#[builder] -#[allow(clippy::needless_pass_by_value)] -pub fn documented( - /// Some documentation for the first argument - /// - /// # Doc test here - /// - /// ``` - /// // Some doc tests as well - /// assert_eq!(2 + 2, 4); - /// ``` - #[builder(default)] - _arg1: String, - - _arg2: &str, - - /// Optional member docs - _arg3: Option, - - _arg4: Vec, - - #[builder(default = - Greeter::start_fn_override() - .name( - "Some intentionally big expression to test the fallback to \ - a code fence in the default value docs" - .to_owned() - ) - .level(42) - .finish_fn_override() - )] - _arg5: Greeter, -) { - eprintln!("Non-const"); -} - -/// Function that returns a greeting special-tailored for a given person -#[builder(builder_type = GreeterBuilderCustom)] -pub fn greet( - /// Name of the person to greet. - /// - /// **Example:** - /// ``` - /// bon_sandbox::greet().name("John"); - /// ``` - name: &str, - - /// Age expressed in full years passed since the birth date. - age: u32, -) -> String { - eprintln!("Non-const"); - format!("Hello {name} with age {age}!") -} - -#[builder] -pub fn fn_with_impl_trait(_arg1: impl std::fmt::Debug + Clone, _arg2: impl std::fmt::Debug) {} - -#[builder] -pub fn many_function_parameters( - _id: Option<&str>, - _keyword: Option<&str>, - _attraction_id: Option<&str>, - _venue_id: Option<&str>, - _postal_code: Option<&str>, - _latlong: Option<&str>, - _radius: Option<&str>, - _unit: Option<&str>, - _source: Option<&str>, - _locale: Option<&str>, - _market_id: Option<&str>, - _start_date_time: Option<&str>, - _end_date_time: Option<&str>, - _include_tba: Option<&str>, - _include_tbd: Option<&str>, - _include_test: Option<&str>, - _size: Option<&str>, - _page: Option<&str>, - _sort: Option<&str>, - _onsale_start_date_time: Option<&str>, - _onsale_end_date_time: Option<&str>, - _city: Option<&str>, - _country_code: Option<&str>, - _state_code: Option<&str>, - _classification_name: Option<&str>, - _classification_id: Option<&str>, - _dma_id: Option<&str>, - _onsale_on_start_date: Option<&str>, - _onsale_on_after_start_date: Option<&str>, - _segment_id: Option<&str>, - _segment_name: Option<&str>, - _promoter_id: Option<&str>, - _client_visibility: Option<&str>, - _nlp: Option<&str>, - _include_licensed_content: Option<&str>, - _geopoint: Option<&str>, -) { - eprintln!("Non-const"); -} diff --git a/bon-sandbox/src/overrides.rs b/bon-sandbox/src/overrides.rs new file mode 100644 index 00000000..8186999b --- /dev/null +++ b/bon-sandbox/src/overrides.rs @@ -0,0 +1,34 @@ +/// Docs on the [`Self`] struct +#[derive(bon::Builder)] +#[builder( + builder_type( + doc { + /// Docs on [`GreeterOverriddenBuilder`] + /// the builder type + }, + name = GreeterOverriddenBuilder, + ), + start_fn( + doc { + /// Docs on + /// [`Self::start_fn_override`] + }, + name = start_fn_override, + ), + finish_fn( + doc { + /// Docs on + /// [`GreeterOverriddenBuilder::finish_fn_override()`] + }, + name = finish_fn_override, + ) +)] +pub struct Greeter { + /// Docs on + /// the `name` field + _name: String, + + /// Docs on + /// the `level` field + _level: usize, +} diff --git a/bon-sandbox/src/private_builder.rs b/bon-sandbox/src/private_builder.rs new file mode 100644 index 00000000..c6915217 --- /dev/null +++ b/bon-sandbox/src/private_builder.rs @@ -0,0 +1,6 @@ +/// Some docs on the private builder +#[derive(bon::Builder)] +#[builder(builder_type(vis = ""))] +pub struct PrivateBuilder { + _field: String, +} diff --git a/bon/src/examples/comprehensive.rs b/bon-sandbox/src/state_mod/comprehensive.rs similarity index 57% rename from bon/src/examples/comprehensive.rs rename to bon-sandbox/src/state_mod/comprehensive.rs index 4333f590..c13181f1 100644 --- a/bon/src/examples/comprehensive.rs +++ b/bon-sandbox/src/state_mod/comprehensive.rs @@ -3,7 +3,7 @@ //! The preliminary reading of [Typestate API](https://bon-rs.com/guide/typestate-api) //! guide is recommended to understand how the pieces in this example fit together. //! -//! This module contains a struct [`Example`] that was annotated with [`#[derive(Builder)]`](crate::Builder). +//! This module contains a struct [`Example`] that was annotated with [`#[derive(Builder)]`](bon::Builder). //! The config [`#[builder(state_mod(vis = "pub"))]`](https://bon-rs.com/reference/builder/top-level/state_mod) //! was applied to make the generated builder's typestate API public and visible here in the docs. //! @@ -12,16 +12,28 @@ //! - [`example_builder`] - the builder's typestate API module /// Example struct with the `#[derive(Builder)]` annotation. -#[derive(crate::Builder)] -#[builder(crate = crate, state_mod(vis = "pub"))] +#[derive(bon::Builder)] +#[builder(state_mod(vis = "pub"))] pub struct Example { - /// Example required member - x1: u32, + required: u32, - /// Example optional member - x2: Option, + optional: Option, - /// Example member with a default value. - #[builder(default = 2 + 2)] - x3: u32, + #[builder(default)] + default: u32, + + #[builder(overwritable)] + overwritable_required: u32, + + #[builder(overwritable)] + overwritable_optional: Option, + + #[builder(overwritable, default = 2 * 2 + 3)] + overwritable_default: u32, + + #[builder(required)] + required_option: Option, + + #[builder(with = |x: &str| -> Result<_, std::num::ParseIntError> { x.parse() })] + with: u32, } diff --git a/bon/src/examples/minimal.rs b/bon-sandbox/src/state_mod/minimal.rs similarity index 83% rename from bon/src/examples/minimal.rs rename to bon-sandbox/src/state_mod/minimal.rs index 751c9fb9..e4f20934 100644 --- a/bon/src/examples/minimal.rs +++ b/bon-sandbox/src/state_mod/minimal.rs @@ -6,8 +6,8 @@ //! [Builder's Type Signature]: https://bon-rs.com/guide/typestate-api/builders-type-signature /// Example struct with the `#[derive(Builder)]` annotation. -#[derive(crate::Builder)] -#[builder(crate = crate, state_mod(vis = "pub"))] +#[derive(bon::Builder)] +#[builder(state_mod(vis = "pub"))] pub struct Example { x1: u32, x2: u32, diff --git a/bon-sandbox/src/state_mod/mod.rs b/bon-sandbox/src/state_mod/mod.rs new file mode 100644 index 00000000..ec64ba4e --- /dev/null +++ b/bon-sandbox/src/state_mod/mod.rs @@ -0,0 +1,4 @@ +//! Examples of docs generated for the builder's typestate API module. + +pub mod comprehensive; +pub mod minimal; diff --git a/bon-sandbox/src/state_mod_pub.rs b/bon-sandbox/src/state_mod_pub.rs deleted file mode 100644 index 21fc1db7..00000000 --- a/bon-sandbox/src/state_mod_pub.rs +++ /dev/null @@ -1,25 +0,0 @@ -#[derive(bon::Builder)] -#[builder(state_mod(vis = "pub"))] -#[allow(dead_code)] -pub struct PubStateMod { - required_arg: u32, - optional_arg: Option, - - #[builder(default)] - default_arg: u32, - - #[builder(overwritable)] - overwritable_required_arg: u32, - - #[builder(overwritable)] - overwritable_optional_arg: Option, - - #[builder(overwritable, default = 2 * 2 + 3)] - overwritable_default_arg: u32, - - #[builder(required)] - required_option_arg: Option, - - #[builder(with = |x: &str| -> Result<_, std::num::ParseIntError> { x.parse() })] - with_arg: u32, -} diff --git a/bon/src/examples/mod.rs b/bon/src/examples/mod.rs deleted file mode 100644 index 4192a67c..00000000 --- a/bon/src/examples/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod comprehensive; -pub mod minimal; diff --git a/bon/src/lib.rs b/bon/src/lib.rs index 9076d325..398a3402 100644 --- a/bon/src/lib.rs +++ b/bon/src/lib.rs @@ -26,7 +26,3 @@ mod collections; pub mod __; mod builder_state; - -/// Examples of generated builders' APIs. -#[cfg(doc)] -pub mod examples; diff --git a/website/src/guide/alternatives.md b/website/src/guide/alternatives.md index 1c4e3f0b..a8d5d8ac 100644 --- a/website/src/guide/alternatives.md +++ b/website/src/guide/alternatives.md @@ -33,6 +33,7 @@ There are several other existing alternative crates for generating builders. `bo | Builder for `fn` hides original `fn` | ✅ | | | | Special setters for collections | [(see below)][collections] | ✅ | | ✅ | | Builder by `&self`/`&mut self` | | | | ✅ | +| [Generates nice docs][gen-docs-cmp] | ✅ | | | ✅ | @@ -86,7 +87,7 @@ Line::builder().x1(1).y1(2).x2(3).y2(4).build(); // [!code error] There are two problems with `#[derive(Builder)]` syntax in this case: 1. This refactoring becomes a breaking change to `Line`'s builder API 😢. -2. The private utility `Point` type leaks through the builder API via `point1`, `point2` setters 😭. +2. The private utility `Point` type leaks through the builder API via `point1`, and `point2` setters 😭. The fundamental problem is that the builder's API is _coupled_ ⛓️ with your struct's internal representation. It's literally `derive`d from the fields of your struct. @@ -143,7 +144,7 @@ And you know what, our old friend `new` doesn't feel offended for being abandone Moreover, it offers you a completely new dimension of flexibility: -- Need some validation? Just make the `new()` method return a `Result`. The generated `build()` method will then become fallible. +- Need some validation? Just change the `new()` method to return a `Result`. The generated `build()` method will then become fallible. - Need to do an `async` operation in the constructor? Just make your constructor `async` and your `build()` will return a `Future`. - Need some adrenaline 💉? Just add `unsafe`, and... you get the idea 😉. @@ -151,9 +152,33 @@ Moreover, it offers you a completely new dimension of flexibility: The chances of hitting a wall with function builders are close to zero, and even if you ever do, you still have access to the [Typestate API](./typestate-api) in `bon` for even more flexibility 💪. -## Documentation Comparison +## Generated Docs Comparison -You can compare the `rustdoc` output for builders generated by different crates. See the source code for this comparison [here]. +Here is a table that compares the `rustdoc` output for builders generated by different crates based on different syntax. Click on the `source` links on the docs pages to see the original source code. + +| Underlying syntax | `bon` | `buildstructor` | `typed-builder` | `derive_builder` | +| ----------------- | -------------------- | ----------------- | ----------------- | ----------------- | +| Struct | [Link][struct-bon] | [Link][struct-bs] | [Link][struct-tb] | [Link][struct-db] | +| Function | [Link][function-bon] | +| Method | [Link][method-bon] | [Link][method-bs] | + +[struct-bon]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/structs/bon/ +[struct-bs]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/structs/buildstructor/ +[struct-tb]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/structs/typed_builder/ +[struct-db]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/structs/derive_builder/ +[function-bon]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/functions/bon/ +[method-bon]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/methods/bon/ +[method-bs]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/methods/buildstructor/ + +All builders were configured to produce roughly similar builder API. The notable exceptions are: + +- `buildstructor` doesn't support `#[builder(default)]` and `#[builder(into)]`-like annotations; +- `buildstructor` doesn't support doc comments on function arguments; +- `derive_builder` doesn't support typestate-based builders; + +Docs generated by `typed-builder` and `buildstructor` suffer from the problem of noisy generics. This problem significantly worsens with the number of fields/arguments in structs/functions. `bon` solves this problem by using a trait-based design for its [typestate](./typestate-api). + +`bon` also includes the default values assigned via [`#[builder(default)]`](../reference/builder/member/default) in the docs ([more examples here](https://docs.rs/bon-sandbox/latest/bon_sandbox/attr_default/struct.ExampleBuilder.html)). ## Special Setter Methods for Collections @@ -180,9 +205,9 @@ Why is there an explicit `main()` function in this code snippet 🤔? It's a lon ::: -This feature isn't available today in `bon`, but it's planned for the future. However, it won't be enabled by default, but rather be opt-in like it is in `derive_builder`. +This feature isn't available today in `bon`, but it's planned for the future. However, it won't be enabled by default; rather, it will be opt-in like it is in `derive_builder`. -The problem with this feature is that a setter that pushes an element into a collection like that may confuse the reader in case if only one element is pushed. This may hide the fact that the member is actually a collection called `friends` in the plural. However, this feature is still useful to provide backwards compatibility when changing the type of a member from `T` or `Option` to `Collection`. +The problem with this feature is that a setter that pushes an element into a collection like that may confuse the reader if only one element is pushed. This may hide the fact that the member is actually a collection called `friends` in the plural. However, this feature is still useful to provide backwards compatibility when changing the type of a member from `T` or `Option` to `Collection`. Alternatively, `bon` provides a separate solution. `bon` exposes the following macros that provide convenient syntax to create collections. @@ -219,6 +244,7 @@ Another difference is that fields of collection types are considered required by [map]: https://docs.rs/bon/latest/bon/macro.map.html [set]: https://docs.rs/bon/latest/bon/macro.set.html [collections]: #special-setter-methods-for-collections +[gen-docs-cmp]: #generated-docs-comparison diff --git a/website/src/guide/benchmarks/compilation.md b/website/src/guide/benchmarks/compilation.md index 64bc60ae..d864d642 100644 --- a/website/src/guide/benchmarks/compilation.md +++ b/website/src/guide/benchmarks/compilation.md @@ -1,56 +1,77 @@ # Compilation Benchmarks -This page describes the results of benchmarking the performance of compiling code generated by `bon`'s and other alternative crates' builder macros. +This page compares the compilation performance with `bon` and alternative builder crates. -There are two things contributing to compile times: +--- + +For any proc macro, two things are contributing to compile times: 1. Compiling the proc macro crate into a dynamic library. -2. Compiling the code generated by the proc macros. +2. Compiling the code generated by the proc macro. + +The benchmarks here intentionally include only `2` in measurements. + +::: details See the reasoning behind this + +The proc macro crate dynamic library is compiled only once and remains in the build cache. For example, once you add `bon` as a dependency, it'll be compiled only once and never recompiled during incremental rebuilds. The cost of that build is rather small and constant. So this isn't of a big interest to the scope of these benchmarks. -The benchmarks here intentionally exclude `1` from measurements. This is because the proc macro crate itself compiles blazingly fast ⚡. For example, once you add `bon` as a dependency, its will compiled only once and never recompiled during incremental rebuilds. +::: ## Measurements The benchmarks measure the time it takes to run `cargo build` against a crate that uses `#[derive(Builder)]` for the given number of structs with the given number of fields in each of them. -### 100 structs with 10 fields +| Builder crate | 10 structs with 50 fields | 100 structs with 10 fields | +| ---------------- | ------------------------- | -------------------------- | +| `bon` | `2.096s` | `2.340s` | +| `typed-builder` | `2.088s` | `1.831s` | +| `derive_builder` | `0.449s` | `1.026s` | +| no macros | `0.112s` | `0.113s` | -| Builder crate | Compile time | -| ---------------- | ------------ | -| `bon` | `2.340s` | -| `typed-builder` | `1.831s` | -| `derive_builder` | `1.026s` | -| no macros | `0.113s` | +## Summary -### 10 structs with 50 fields +Builder macros do add noticeable overhead to the compilation performance due to the number of additional structs and methods they generate. -| Builder crate | Compile time | -| ---------------- | ------------ | -| `bon` | `2.096s` | -| `typed-builder` | `2.088s` | -| `derive_builder` | `0.449s` | -| no macros | `0.112s` | +`bon` has more compile time overhead than other crates, which is likely still reasonable, but let's understand why and what we get in return from this. -## Summary +### Why does `bon` lose to `typed-builder` in compilation perf? + +`bon`'s generated code is a bit more complex than `typed-builder`'s, because `bon` generates additional traits and structs to expose a nice and stable [typestate API](../typestate-api). -As you can see the code generated by `bon` takes more time to compile than with other builder crates. It is close to `typed-builder` in the [second](#10-structs-with-50-fields) benchmark though. +This is also done to reduce the builder's type signature size and reduce generic type noise in the generated builders' docs. See [docs comparison](../alternatives#generated-docs-comparison) (the difference is drastic). -Now don't rush to conclusions ✋. To be fair, the amount of features and improvements `bon` provides over other crates is worth the slightly higher compilation time. The difference isn't that critical with the number of structs/fields used in the measurements here. +### Can `bon` improve compile times? -However, let's address some questions. +Definitely, but it comes at a cost 🪙. `bon` prioritizes the convenience of the generated builder API, documentation cleanness, and the level of compile-time checks. + +If you'd like to improve your compile times, consider disabling compile-time checks for overwrites of optional members in setters with [`#[builder(overwritable)]`](../../reference/builder/member/overwritable). However, don't rush with that, think carefully about the trade you would make. ### Why `derive_builder` is fastest to compile? -The main contributor to compile times of code generated by `bon` and `typed-builder` is their usage of generics to represent the type state. The builders generated by `derive_builder` don't use any generics. +The main contributor to compile times of code generated by `bon` and `typed-builder` is their usage of generics to represent the typestate. Builders generated by `derive_builder` don't use any generics. The main downside of `derive_builder`'s approach is that its finishing `build()` method always returns a `Result`, because it needs to validate, that all required fields were set **at runtime**. -### Why `bon` loses to `typed-builder` in compilation perf? +### Is this all worth compilation time overhead? + +It depends on your use case. + +If you are considering builders in your crate's public API, then it's definitely worth it. One of the main focus areas of `bon` is breaking change prevention (i.e. [Compatibility](../basics/compatibility)) and builder API ergonomics. This way you can provide stable, evolvable and convenient API for your users. + +If you are considering builders in your private modules, then the main feature of `bon` you'd be interested in is [optional members](../basics/optional-members) and nicer syntax. + +The general rule is that builders make more sense for pervasive structs and functions that you have to construct/call frequently. Don't blindly add builders to every other struct or function. If that struct or function is used only in a single place in your code, then using a builder for it may be unnecessary. + +## Hardware + +The benchmarks were run on a dedicated root server `AX51-NVMe` on [Hetzner](https://www.hetzner.com/). -`bon`'s generated code is a bit more complex than `typed-builder`'s, because `bon` generates additional traits and types to expose a nice and stable [typestate API](../typestate-api). +- OS: Ubuntu 22.04.4 (Linux 5.15.0-76-generic) +- CPU: AMD Ryzen 7 3700X 8-Core Processor (x86_64) +- RAM: 62.8 GiB -This is also done to reduce the builder's type signature size and reduce the noisy generic in the documentation generated by `rustdoc`. In fact, the difference in the generated docs between `bon` and `typed-builder` is [drastic](../alternatives#documentation-comparison). +## References -### Can `bon` do better for compile times? +The source code of the benchmarks is [available here][benchmarks-source]. -Unfortunately, it's a tradeoff. +[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/runtime diff --git a/website/src/guide/benchmarks/runtime.md b/website/src/guide/benchmarks/runtime.md index bcb7d908..07369456 100644 --- a/website/src/guide/benchmarks/runtime.md +++ b/website/src/guide/benchmarks/runtime.md @@ -74,4 +74,4 @@ The benchmarks were run on a dedicated root server `AX51-NVMe` on [Hetzner](http The source code of the benchmarks is [available here][benchmarks-source]. -[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/runtime +[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/compilation diff --git a/website/src/index.md b/website/src/index.md index 5e0a5c7f..b7efe1ac 100644 --- a/website/src/index.md +++ b/website/src/index.md @@ -12,6 +12,9 @@ hero: - theme: brand text: Guide link: /guide/overview + - theme: brand + text: Reference + link: /reference/builder - theme: alt text: Blog link: /blog diff --git a/website/src/reference/builder/member/default.md b/website/src/reference/builder/member/default.md index db968bf8..efbb34d8 100644 --- a/website/src/reference/builder/member/default.md +++ b/website/src/reference/builder/member/default.md @@ -146,7 +146,7 @@ assert_eq!(value.x3, "lyra"); ::: -## Evaluation context +## Evaluation Context You can use the values of other members by referencing their names in the `default` expression. All members are initialized in the order of their declaration. It means only those members that are declared earlier (higher) in the code are available to the `default` expression. @@ -238,6 +238,12 @@ assert_eq!(value, (3, 6, 9)); The `self` parameter in associated method syntax is not available to the `default` expression. If you need the `self` context for your defaulting logic, then set your member's type to `Option` and handle the defaulting in the function's body manually. -## Compile errors +## Compile Errors This attribute is incompatible with members of `Option` type, since `Option` already implies the default value of `None`. However, it can be used together with [`#[builder(required)]`](./required). + +## Generated Docs + +The documentation for the setters will include the default value expression. If you use `#[builder(default)]`, then the default value expression will be inferred for primitive and some well-known types. + +See [examples of the generated docs](https://docs.rs/bon-sandbox/latest/bon_sandbox/attr_default/struct.ExampleBuilder.html) with `#[builder(default)]`. From f7377fe72c34150f4779a0087dc66dfe81b1083a Mon Sep 17 00:00:00 2001 From: Veetaha Date: Sat, 9 Nov 2024 02:37:43 +0000 Subject: [PATCH 3/6] Remove `bon-overwritable` from benchmarks --- README.v3.md | 2 + benchmarks/compilation/codegen/src/main.rs | 8 +- .../compilation/src/structs_100_fields_10.rs | 100 ------------------ .../compilation/src/structs_10_fields_50.rs | 10 -- 4 files changed, 4 insertions(+), 116 deletions(-) diff --git a/README.v3.md b/README.v3.md index 9df8f043..1117c9b2 100644 --- a/README.v3.md +++ b/README.v3.md @@ -208,6 +208,8 @@ See [alternatives](https://bon-rs.com/guide/alternatives) for comparison. ## Who's Using `bon`? +Some notable users: + - [`crates.io` backend](https://github.com/rust-lang/crates.io) - [`ractor`](https://github.com/slawlor/ractor) - [`comrak`](https://github.com/kivikakk/comrak) diff --git a/benchmarks/compilation/codegen/src/main.rs b/benchmarks/compilation/codegen/src/main.rs index 084b4411..be862ad2 100644 --- a/benchmarks/compilation/codegen/src/main.rs +++ b/benchmarks/compilation/codegen/src/main.rs @@ -10,8 +10,8 @@ fn main() -> anyhow::Result<()> { let src_dir = bench_dir.join("src"); - let structs_number = 100; - let fields_number = 10; + let structs_number = 10; + let fields_number = 50; std::fs::write( src_dir.join(format!( @@ -51,10 +51,6 @@ fn structs_n_fields_n(structs_number: usize, fields_number: usize) -> TokenStrea ), derive(crate::Builder), )] - #[cfg_attr( - feature = "bon-overwritable", - builder(on(_, overwritable)), - )] pub struct #struct_name { #( #field_names: i32, )* } diff --git a/benchmarks/compilation/src/structs_100_fields_10.rs b/benchmarks/compilation/src/structs_100_fields_10.rs index a7e1992b..2f1f0c43 100644 --- a/benchmarks/compilation/src/structs_100_fields_10.rs +++ b/benchmarks/compilation/src/structs_100_fields_10.rs @@ -2,7 +2,6 @@ any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct1 { x1: i32, x2: i32, @@ -19,7 +18,6 @@ pub struct Struct1 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct2 { x1: i32, x2: i32, @@ -36,7 +34,6 @@ pub struct Struct2 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct3 { x1: i32, x2: i32, @@ -53,7 +50,6 @@ pub struct Struct3 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct4 { x1: i32, x2: i32, @@ -70,7 +66,6 @@ pub struct Struct4 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct5 { x1: i32, x2: i32, @@ -87,7 +82,6 @@ pub struct Struct5 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct6 { x1: i32, x2: i32, @@ -104,7 +98,6 @@ pub struct Struct6 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct7 { x1: i32, x2: i32, @@ -121,7 +114,6 @@ pub struct Struct7 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct8 { x1: i32, x2: i32, @@ -138,7 +130,6 @@ pub struct Struct8 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct9 { x1: i32, x2: i32, @@ -155,7 +146,6 @@ pub struct Struct9 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct10 { x1: i32, x2: i32, @@ -172,7 +162,6 @@ pub struct Struct10 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct11 { x1: i32, x2: i32, @@ -189,7 +178,6 @@ pub struct Struct11 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct12 { x1: i32, x2: i32, @@ -206,7 +194,6 @@ pub struct Struct12 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct13 { x1: i32, x2: i32, @@ -223,7 +210,6 @@ pub struct Struct13 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct14 { x1: i32, x2: i32, @@ -240,7 +226,6 @@ pub struct Struct14 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct15 { x1: i32, x2: i32, @@ -257,7 +242,6 @@ pub struct Struct15 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct16 { x1: i32, x2: i32, @@ -274,7 +258,6 @@ pub struct Struct16 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct17 { x1: i32, x2: i32, @@ -291,7 +274,6 @@ pub struct Struct17 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct18 { x1: i32, x2: i32, @@ -308,7 +290,6 @@ pub struct Struct18 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct19 { x1: i32, x2: i32, @@ -325,7 +306,6 @@ pub struct Struct19 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct20 { x1: i32, x2: i32, @@ -342,7 +322,6 @@ pub struct Struct20 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct21 { x1: i32, x2: i32, @@ -359,7 +338,6 @@ pub struct Struct21 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct22 { x1: i32, x2: i32, @@ -376,7 +354,6 @@ pub struct Struct22 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct23 { x1: i32, x2: i32, @@ -393,7 +370,6 @@ pub struct Struct23 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct24 { x1: i32, x2: i32, @@ -410,7 +386,6 @@ pub struct Struct24 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct25 { x1: i32, x2: i32, @@ -427,7 +402,6 @@ pub struct Struct25 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct26 { x1: i32, x2: i32, @@ -444,7 +418,6 @@ pub struct Struct26 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct27 { x1: i32, x2: i32, @@ -461,7 +434,6 @@ pub struct Struct27 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct28 { x1: i32, x2: i32, @@ -478,7 +450,6 @@ pub struct Struct28 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct29 { x1: i32, x2: i32, @@ -495,7 +466,6 @@ pub struct Struct29 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct30 { x1: i32, x2: i32, @@ -512,7 +482,6 @@ pub struct Struct30 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct31 { x1: i32, x2: i32, @@ -529,7 +498,6 @@ pub struct Struct31 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct32 { x1: i32, x2: i32, @@ -546,7 +514,6 @@ pub struct Struct32 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct33 { x1: i32, x2: i32, @@ -563,7 +530,6 @@ pub struct Struct33 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct34 { x1: i32, x2: i32, @@ -580,7 +546,6 @@ pub struct Struct34 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct35 { x1: i32, x2: i32, @@ -597,7 +562,6 @@ pub struct Struct35 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct36 { x1: i32, x2: i32, @@ -614,7 +578,6 @@ pub struct Struct36 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct37 { x1: i32, x2: i32, @@ -631,7 +594,6 @@ pub struct Struct37 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct38 { x1: i32, x2: i32, @@ -648,7 +610,6 @@ pub struct Struct38 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct39 { x1: i32, x2: i32, @@ -665,7 +626,6 @@ pub struct Struct39 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct40 { x1: i32, x2: i32, @@ -682,7 +642,6 @@ pub struct Struct40 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct41 { x1: i32, x2: i32, @@ -699,7 +658,6 @@ pub struct Struct41 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct42 { x1: i32, x2: i32, @@ -716,7 +674,6 @@ pub struct Struct42 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct43 { x1: i32, x2: i32, @@ -733,7 +690,6 @@ pub struct Struct43 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct44 { x1: i32, x2: i32, @@ -750,7 +706,6 @@ pub struct Struct44 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct45 { x1: i32, x2: i32, @@ -767,7 +722,6 @@ pub struct Struct45 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct46 { x1: i32, x2: i32, @@ -784,7 +738,6 @@ pub struct Struct46 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct47 { x1: i32, x2: i32, @@ -801,7 +754,6 @@ pub struct Struct47 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct48 { x1: i32, x2: i32, @@ -818,7 +770,6 @@ pub struct Struct48 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct49 { x1: i32, x2: i32, @@ -835,7 +786,6 @@ pub struct Struct49 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct50 { x1: i32, x2: i32, @@ -852,7 +802,6 @@ pub struct Struct50 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct51 { x1: i32, x2: i32, @@ -869,7 +818,6 @@ pub struct Struct51 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct52 { x1: i32, x2: i32, @@ -886,7 +834,6 @@ pub struct Struct52 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct53 { x1: i32, x2: i32, @@ -903,7 +850,6 @@ pub struct Struct53 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct54 { x1: i32, x2: i32, @@ -920,7 +866,6 @@ pub struct Struct54 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct55 { x1: i32, x2: i32, @@ -937,7 +882,6 @@ pub struct Struct55 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct56 { x1: i32, x2: i32, @@ -954,7 +898,6 @@ pub struct Struct56 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct57 { x1: i32, x2: i32, @@ -971,7 +914,6 @@ pub struct Struct57 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct58 { x1: i32, x2: i32, @@ -988,7 +930,6 @@ pub struct Struct58 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct59 { x1: i32, x2: i32, @@ -1005,7 +946,6 @@ pub struct Struct59 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct60 { x1: i32, x2: i32, @@ -1022,7 +962,6 @@ pub struct Struct60 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct61 { x1: i32, x2: i32, @@ -1039,7 +978,6 @@ pub struct Struct61 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct62 { x1: i32, x2: i32, @@ -1056,7 +994,6 @@ pub struct Struct62 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct63 { x1: i32, x2: i32, @@ -1073,7 +1010,6 @@ pub struct Struct63 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct64 { x1: i32, x2: i32, @@ -1090,7 +1026,6 @@ pub struct Struct64 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct65 { x1: i32, x2: i32, @@ -1107,7 +1042,6 @@ pub struct Struct65 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct66 { x1: i32, x2: i32, @@ -1124,7 +1058,6 @@ pub struct Struct66 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct67 { x1: i32, x2: i32, @@ -1141,7 +1074,6 @@ pub struct Struct67 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct68 { x1: i32, x2: i32, @@ -1158,7 +1090,6 @@ pub struct Struct68 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct69 { x1: i32, x2: i32, @@ -1175,7 +1106,6 @@ pub struct Struct69 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct70 { x1: i32, x2: i32, @@ -1192,7 +1122,6 @@ pub struct Struct70 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct71 { x1: i32, x2: i32, @@ -1209,7 +1138,6 @@ pub struct Struct71 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct72 { x1: i32, x2: i32, @@ -1226,7 +1154,6 @@ pub struct Struct72 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct73 { x1: i32, x2: i32, @@ -1243,7 +1170,6 @@ pub struct Struct73 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct74 { x1: i32, x2: i32, @@ -1260,7 +1186,6 @@ pub struct Struct74 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct75 { x1: i32, x2: i32, @@ -1277,7 +1202,6 @@ pub struct Struct75 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct76 { x1: i32, x2: i32, @@ -1294,7 +1218,6 @@ pub struct Struct76 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct77 { x1: i32, x2: i32, @@ -1311,7 +1234,6 @@ pub struct Struct77 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct78 { x1: i32, x2: i32, @@ -1328,7 +1250,6 @@ pub struct Struct78 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct79 { x1: i32, x2: i32, @@ -1345,7 +1266,6 @@ pub struct Struct79 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct80 { x1: i32, x2: i32, @@ -1362,7 +1282,6 @@ pub struct Struct80 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct81 { x1: i32, x2: i32, @@ -1379,7 +1298,6 @@ pub struct Struct81 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct82 { x1: i32, x2: i32, @@ -1396,7 +1314,6 @@ pub struct Struct82 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct83 { x1: i32, x2: i32, @@ -1413,7 +1330,6 @@ pub struct Struct83 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct84 { x1: i32, x2: i32, @@ -1430,7 +1346,6 @@ pub struct Struct84 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct85 { x1: i32, x2: i32, @@ -1447,7 +1362,6 @@ pub struct Struct85 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct86 { x1: i32, x2: i32, @@ -1464,7 +1378,6 @@ pub struct Struct86 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct87 { x1: i32, x2: i32, @@ -1481,7 +1394,6 @@ pub struct Struct87 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct88 { x1: i32, x2: i32, @@ -1498,7 +1410,6 @@ pub struct Struct88 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct89 { x1: i32, x2: i32, @@ -1515,7 +1426,6 @@ pub struct Struct89 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct90 { x1: i32, x2: i32, @@ -1532,7 +1442,6 @@ pub struct Struct90 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct91 { x1: i32, x2: i32, @@ -1549,7 +1458,6 @@ pub struct Struct91 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct92 { x1: i32, x2: i32, @@ -1566,7 +1474,6 @@ pub struct Struct92 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct93 { x1: i32, x2: i32, @@ -1583,7 +1490,6 @@ pub struct Struct93 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct94 { x1: i32, x2: i32, @@ -1600,7 +1506,6 @@ pub struct Struct94 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct95 { x1: i32, x2: i32, @@ -1617,7 +1522,6 @@ pub struct Struct95 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct96 { x1: i32, x2: i32, @@ -1634,7 +1538,6 @@ pub struct Struct96 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct97 { x1: i32, x2: i32, @@ -1651,7 +1554,6 @@ pub struct Struct97 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct98 { x1: i32, x2: i32, @@ -1668,7 +1570,6 @@ pub struct Struct98 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct99 { x1: i32, x2: i32, @@ -1685,7 +1586,6 @@ pub struct Struct99 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct100 { x1: i32, x2: i32, diff --git a/benchmarks/compilation/src/structs_10_fields_50.rs b/benchmarks/compilation/src/structs_10_fields_50.rs index 8f3edea1..e3026f62 100644 --- a/benchmarks/compilation/src/structs_10_fields_50.rs +++ b/benchmarks/compilation/src/structs_10_fields_50.rs @@ -2,7 +2,6 @@ any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct1 { x1: i32, x2: i32, @@ -59,7 +58,6 @@ pub struct Struct1 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct2 { x1: i32, x2: i32, @@ -116,7 +114,6 @@ pub struct Struct2 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct3 { x1: i32, x2: i32, @@ -173,7 +170,6 @@ pub struct Struct3 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct4 { x1: i32, x2: i32, @@ -230,7 +226,6 @@ pub struct Struct4 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct5 { x1: i32, x2: i32, @@ -287,7 +282,6 @@ pub struct Struct5 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct6 { x1: i32, x2: i32, @@ -344,7 +338,6 @@ pub struct Struct6 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct7 { x1: i32, x2: i32, @@ -401,7 +394,6 @@ pub struct Struct7 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct8 { x1: i32, x2: i32, @@ -458,7 +450,6 @@ pub struct Struct8 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct9 { x1: i32, x2: i32, @@ -515,7 +506,6 @@ pub struct Struct9 { any(feature = "bon", feature = "typed-builder", feature = "derive_builder",), derive(crate::Builder) )] -#[cfg_attr(feature = "bon-overwritable", builder(on(_, overwritable)))] pub struct Struct10 { x1: i32, x2: i32, From bd86495983402abb6b7f1bb0a559ea0c125fe35b Mon Sep 17 00:00:00 2001 From: Veetaha Date: Sat, 9 Nov 2024 02:44:41 +0000 Subject: [PATCH 4/6] Fix CI --- .../tests/snapshots/setters_docs_and_vis.rs | 75 ++++--------------- bon-sandbox/src/functions.rs | 2 +- e2e-tests/Cargo.toml | 31 -------- website/doctests/Cargo.toml | 4 +- 4 files changed, 15 insertions(+), 97 deletions(-) delete mode 100644 e2e-tests/Cargo.toml diff --git a/bon-macros/tests/snapshots/setters_docs_and_vis.rs b/bon-macros/tests/snapshots/setters_docs_and_vis.rs index 52763184..86e53902 100644 --- a/bon-macros/tests/snapshots/setters_docs_and_vis.rs +++ b/bon-macros/tests/snapshots/setters_docs_and_vis.rs @@ -2,8 +2,7 @@ #[automatically_derived] #[allow(deprecated)] impl SutBuilder { - /**| **Required** | -| -- | + /**_**Required.**_ */ /// Docs on the required field setters. @@ -15,11 +14,7 @@ impl SutBuilder { where S::RequiredField: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`maybe_optional_field()`](Self::maybe_optional_field), which is a companion setter that accepts an `Option`. - + /**_**Optional** ( [Some](Self::optional_field()) / [Option](Self::maybe_optional_field()) setters)._ */ /// Docs on the optional field setters. @@ -31,11 +26,7 @@ impl SutBuilder { where S::OptionalField: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`optional_field()`](Self::optional_field), which is a companion setter that wraps the value with `Some` internally. - + /**_**Optional** ( [Some](Self::optional_field()) / [Option](Self::maybe_optional_field()) setters)._ */ /// Docs on the optional field setters. @@ -47,13 +38,9 @@ impl SutBuilder { where S::OptionalField: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`maybe_default_field()`](Self::maybe_default_field), which is a companion setter that accepts an `Option`. + /**_**Optional** ( [Some](Self::default_field()) / [Option](Self::maybe_default_field()) setters)._ _**Default:**_ ```2 + 2 * 3```. -**Default:** ```2 + 2 * 3```. */ /// Docs on the default field setters. @@ -65,14 +52,10 @@ impl SutBuilder { where S::DefaultField: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | + /**_**Optional** ( [Some](Self::default_field()) / [Option](Self::maybe_default_field()) setters)._ _**Default:**_ ```2 + 2 * 3```. -**See also** [`default_field()`](Self::default_field), which is a companion setter that wraps the value with `Some` internally. -**Default:** ```2 + 2 * 3```. - */ /// Docs on the default field setters. /// Multiline. @@ -83,11 +66,7 @@ impl SutBuilder { where S::DefaultField: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`maybe_optional_field_with_specific_overrides()`](Self::maybe_optional_field_with_specific_overrides), which is a companion setter that accepts an `Option`. - + /**_**Optional** ( [Some](Self::optional_field_with_specific_overrides()) / [Option](Self::maybe_optional_field_with_specific_overrides()) setters)._ */ /// Docs on some_fn @@ -99,11 +78,7 @@ impl SutBuilder { where S::OptionalFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`optional_field_with_specific_overrides()`](Self::optional_field_with_specific_overrides), which is a companion setter that wraps the value with `Some` internally. - + /**_**Optional** ( [Some](Self::optional_field_with_specific_overrides()) / [Option](Self::maybe_optional_field_with_specific_overrides()) setters)._ */ /// Docs on option_fn @@ -115,13 +90,9 @@ impl SutBuilder { where S::OptionalFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`maybe_default_field_with_specific_overrides()`](Self::maybe_default_field_with_specific_overrides), which is a companion setter that accepts an `Option`. + /**_**Optional** ( [Some](Self::default_field_with_specific_overrides()) / [Option](Self::maybe_default_field_with_specific_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. -**Default:** ```2 + 2 * 3```. */ /// Docs on some_fn @@ -133,13 +104,9 @@ impl SutBuilder { where S::DefaultFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`default_field_with_specific_overrides()`](Self::default_field_with_specific_overrides), which is a companion setter that wraps the value with `Some` internally. + /**_**Optional** ( [Some](Self::default_field_with_specific_overrides()) / [Option](Self::maybe_default_field_with_specific_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. -**Default:** ```2 + 2 * 3```. */ /// Docs on option_fn @@ -151,11 +118,7 @@ impl SutBuilder { where S::DefaultFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`maybe_optional_field_with_inherited_overrides()`](Self::maybe_optional_field_with_inherited_overrides), which is a companion setter that accepts an `Option`. - + /**_**Optional** ( [Some](Self::optional_field_with_inherited_overrides()) / [Option](Self::maybe_optional_field_with_inherited_overrides()) setters)._ */ /// Common docs @@ -167,11 +130,7 @@ impl SutBuilder { where S::OptionalFieldWithInheritedOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`optional_field_with_inherited_overrides()`](Self::optional_field_with_inherited_overrides), which is a companion setter that wraps the value with `Some` internally. - + /**_**Optional** ( [Some](Self::optional_field_with_inherited_overrides()) / [Option](Self::maybe_optional_field_with_inherited_overrides()) setters)._ */ /// Docs on option_fn @@ -183,14 +142,10 @@ impl SutBuilder { where S::OptionalFieldWithInheritedOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | + /**_**Optional** ( [Some](Self::default_field_with_inherited_overrides()) / [Option](Self::maybe_default_field_with_inherited_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. -**See also** [`maybe_default_field_with_inherited_overrides()`](Self::maybe_default_field_with_inherited_overrides), which is a companion setter that accepts an `Option`. -**Default:** ```2 + 2 * 3```. - */ /// Common docs /// Multiline. @@ -201,13 +156,9 @@ impl SutBuilder { where S::DefaultFieldWithInheritedOverrides: sut_builder::IsUnset, {} - /**| **Optional** | -| -- | - -**See also** [`default_field_with_inherited_overrides()`](Self::default_field_with_inherited_overrides), which is a companion setter that wraps the value with `Some` internally. + /**_**Optional** ( [Some](Self::default_field_with_inherited_overrides()) / [Option](Self::maybe_default_field_with_inherited_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. -**Default:** ```2 + 2 * 3```. */ /// Docs on option_fn diff --git a/bon-sandbox/src/functions.rs b/bon-sandbox/src/functions.rs index 3dc2d396..d19513bc 100644 --- a/bon-sandbox/src/functions.rs +++ b/bon-sandbox/src/functions.rs @@ -63,7 +63,7 @@ pub fn greet( /// /// **Example:** /// ``` - /// bon_sandbox::greet().name("John"); + /// bon_sandbox::functions::greet().name("John"); /// ``` name: &str, diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml deleted file mode 100644 index 9b19bde9..00000000 --- a/e2e-tests/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "e2e-tests" -version = "0.1.0" - -publish = false - -description = """ - Crate for manual end-to-end testing the `bon` crate. For example it's used to check - the quality of the documentation produced by `cargo doc` for the macro-generated - APIs. - - We also use this crate to test the code examples in the documentation in the `website`. -""" - -edition = "2021" - -[lints] -workspace = true - -[dependencies] -bon = { path = "../bon", features = ["experimental-overwritable"] } - -[dev-dependencies] -anyhow = "1.0" -buildstructor = "0.5" -macro_rules_attribute = "0.2" - -[build-dependencies] -itertools = "0.13" -lazy-regex = "3.3" -walkdir = "2.5" diff --git a/website/doctests/Cargo.toml b/website/doctests/Cargo.toml index 9c790ebb..9ba2ad28 100644 --- a/website/doctests/Cargo.toml +++ b/website/doctests/Cargo.toml @@ -11,11 +11,9 @@ edition = "2021" [lints] workspace = true -[dependencies] -bon = { path = "../../bon", features = ["experimental-overwritable"] } - [dev-dependencies] anyhow = "1.0" +bon = { path = "../../bon", features = ["experimental-overwritable"] } buildstructor = "0.5" macro_rules_attribute = "0.2" From 27ac852e168fea868af2bed7d1318df69ea8d08b Mon Sep 17 00:00:00 2001 From: Veetaha Date: Sat, 9 Nov 2024 02:47:11 +0000 Subject: [PATCH 5/6] Fix ci --- bon-sandbox/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bon-sandbox/Cargo.toml b/bon-sandbox/Cargo.toml index 4dd3c2ab..b0c98301 100644 --- a/bon-sandbox/Cargo.toml +++ b/bon-sandbox/Cargo.toml @@ -29,7 +29,7 @@ targets = ["x86_64-unknown-linux-gnu"] workspace = true [dependencies] -bon = { path = "../bon", version = "=2.3.0" } +bon = { path = "../bon", version = "=2.3.0", features = ["experimental-overwritable"] } buildstructor = "0.5" derive_builder = "0.20" typed-builder = "0.20" From 46dd0b78b02e9b25e655a6deeec6fdf11e1c67d4 Mon Sep 17 00:00:00 2001 From: Veetaha Date: Sat, 9 Nov 2024 03:16:35 +0000 Subject: [PATCH 6/6] Self-review --- .../src/builder/builder_gen/setters/mod.rs | 9 ++++--- .../tests/snapshots/setters_docs_and_vis.rs | 24 +++++++++---------- bon-sandbox/Cargo.toml | 2 +- bon-sandbox/src/lib.rs | 2 +- bon-sandbox/src/state_mod/minimal.rs | 3 +-- website/doctests/Cargo.toml | 2 +- website/doctests/src/lib.rs | 2 +- website/src/changelog.md | 2 +- website/src/guide/alternatives.md | 4 ++-- website/src/guide/benchmarks/compilation.md | 6 ++--- website/src/guide/benchmarks/runtime.md | 2 +- 11 files changed, 30 insertions(+), 28 deletions(-) diff --git a/bon-macros/src/builder/builder_gen/setters/mod.rs b/bon-macros/src/builder/builder_gen/setters/mod.rs index db310c15..6d8a1dc9 100644 --- a/bon-macros/src/builder/builder_gen/setters/mod.rs +++ b/bon-macros/src/builder/builder_gen/setters/mod.rs @@ -619,9 +619,12 @@ fn optional_setter_docs( }) .unwrap_or_default(); - let setters = format!(" [Some](Self::{some_fn}()) / [Option](Self::{option_fn}()) setters"); - - format!("_**Optional** ({setters})._{default}\n\n",) + format!( + "_**Optional** \ + ([Some](Self::{some_fn}()) / [Option](Self::{option_fn}()) setters).\ + _{default}\ + \n\n" + ) } fn well_known_default(ty: &syn::Type) -> Option { diff --git a/bon-macros/tests/snapshots/setters_docs_and_vis.rs b/bon-macros/tests/snapshots/setters_docs_and_vis.rs index 86e53902..7480a35d 100644 --- a/bon-macros/tests/snapshots/setters_docs_and_vis.rs +++ b/bon-macros/tests/snapshots/setters_docs_and_vis.rs @@ -14,7 +14,7 @@ impl SutBuilder { where S::RequiredField: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::optional_field()) / [Option](Self::maybe_optional_field()) setters)._ + /**_**Optional** ([Some](Self::optional_field()) / [Option](Self::maybe_optional_field()) setters)._ */ /// Docs on the optional field setters. @@ -26,7 +26,7 @@ impl SutBuilder { where S::OptionalField: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::optional_field()) / [Option](Self::maybe_optional_field()) setters)._ + /**_**Optional** ([Some](Self::optional_field()) / [Option](Self::maybe_optional_field()) setters)._ */ /// Docs on the optional field setters. @@ -38,7 +38,7 @@ impl SutBuilder { where S::OptionalField: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::default_field()) / [Option](Self::maybe_default_field()) setters)._ _**Default:**_ ```2 + 2 * 3```. + /**_**Optional** ([Some](Self::default_field()) / [Option](Self::maybe_default_field()) setters)._ _**Default:**_ ```2 + 2 * 3```. @@ -52,7 +52,7 @@ impl SutBuilder { where S::DefaultField: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::default_field()) / [Option](Self::maybe_default_field()) setters)._ _**Default:**_ ```2 + 2 * 3```. + /**_**Optional** ([Some](Self::default_field()) / [Option](Self::maybe_default_field()) setters)._ _**Default:**_ ```2 + 2 * 3```. @@ -66,7 +66,7 @@ impl SutBuilder { where S::DefaultField: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::optional_field_with_specific_overrides()) / [Option](Self::maybe_optional_field_with_specific_overrides()) setters)._ + /**_**Optional** ([Some](Self::optional_field_with_specific_overrides()) / [Option](Self::maybe_optional_field_with_specific_overrides()) setters)._ */ /// Docs on some_fn @@ -78,7 +78,7 @@ impl SutBuilder { where S::OptionalFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::optional_field_with_specific_overrides()) / [Option](Self::maybe_optional_field_with_specific_overrides()) setters)._ + /**_**Optional** ([Some](Self::optional_field_with_specific_overrides()) / [Option](Self::maybe_optional_field_with_specific_overrides()) setters)._ */ /// Docs on option_fn @@ -90,7 +90,7 @@ impl SutBuilder { where S::OptionalFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::default_field_with_specific_overrides()) / [Option](Self::maybe_default_field_with_specific_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. + /**_**Optional** ([Some](Self::default_field_with_specific_overrides()) / [Option](Self::maybe_default_field_with_specific_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. @@ -104,7 +104,7 @@ impl SutBuilder { where S::DefaultFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::default_field_with_specific_overrides()) / [Option](Self::maybe_default_field_with_specific_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. + /**_**Optional** ([Some](Self::default_field_with_specific_overrides()) / [Option](Self::maybe_default_field_with_specific_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. @@ -118,7 +118,7 @@ impl SutBuilder { where S::DefaultFieldWithSpecificOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::optional_field_with_inherited_overrides()) / [Option](Self::maybe_optional_field_with_inherited_overrides()) setters)._ + /**_**Optional** ([Some](Self::optional_field_with_inherited_overrides()) / [Option](Self::maybe_optional_field_with_inherited_overrides()) setters)._ */ /// Common docs @@ -130,7 +130,7 @@ impl SutBuilder { where S::OptionalFieldWithInheritedOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::optional_field_with_inherited_overrides()) / [Option](Self::maybe_optional_field_with_inherited_overrides()) setters)._ + /**_**Optional** ([Some](Self::optional_field_with_inherited_overrides()) / [Option](Self::maybe_optional_field_with_inherited_overrides()) setters)._ */ /// Docs on option_fn @@ -142,7 +142,7 @@ impl SutBuilder { where S::OptionalFieldWithInheritedOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::default_field_with_inherited_overrides()) / [Option](Self::maybe_default_field_with_inherited_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. + /**_**Optional** ([Some](Self::default_field_with_inherited_overrides()) / [Option](Self::maybe_default_field_with_inherited_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. @@ -156,7 +156,7 @@ impl SutBuilder { where S::DefaultFieldWithInheritedOverrides: sut_builder::IsUnset, {} - /**_**Optional** ( [Some](Self::default_field_with_inherited_overrides()) / [Option](Self::maybe_default_field_with_inherited_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. + /**_**Optional** ([Some](Self::default_field_with_inherited_overrides()) / [Option](Self::maybe_default_field_with_inherited_overrides()) setters)._ _**Default:**_ ```2 + 2 * 3```. diff --git a/bon-sandbox/Cargo.toml b/bon-sandbox/Cargo.toml index b0c98301..02c364b5 100644 --- a/bon-sandbox/Cargo.toml +++ b/bon-sandbox/Cargo.toml @@ -6,7 +6,7 @@ description = """ Not a real crate! It's just a showcase of examples used by `bon`'s documentation to demonstrate the rustdoc output for code generated by builder macros. - Don't use this crate, it doesn't follow semver at all and serves no other puprose + Don't use this crate, it doesn't follow semver at all and serves no other purpose other than linking to its docs as an example! """ diff --git a/bon-sandbox/src/lib.rs b/bon-sandbox/src/lib.rs index a2385463..9cd816e8 100644 --- a/bon-sandbox/src/lib.rs +++ b/bon-sandbox/src/lib.rs @@ -1,7 +1,7 @@ //! Not a real crate! It's just a showcase of examples used by `bon`'s documentation //! to demonstrate the rustdoc output for code generated by builder macros. //! -//! Don't use this crate, it doesn't follow semver at all and serves no other puprose +//! Don't use this crate, it doesn't follow semver at all and serves no other purpose //! other than linking to its docs as an example! #![allow(missing_debug_implementations, missing_docs, dead_code)] diff --git a/bon-sandbox/src/state_mod/minimal.rs b/bon-sandbox/src/state_mod/minimal.rs index e4f20934..253d102b 100644 --- a/bon-sandbox/src/state_mod/minimal.rs +++ b/bon-sandbox/src/state_mod/minimal.rs @@ -1,7 +1,6 @@ //! Minimal example of the generated builder and its typestate API. //! -//! This documentation was generated as a showcase for the [Builder's Type Signature] -//! guide +//! This documentation was generated as a showcase for the [Builder's Type Signature] guide. //! //! [Builder's Type Signature]: https://bon-rs.com/guide/typestate-api/builders-type-signature diff --git a/website/doctests/Cargo.toml b/website/doctests/Cargo.toml index 9ba2ad28..27447b5d 100644 --- a/website/doctests/Cargo.toml +++ b/website/doctests/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" publish = false -description = "Crate for testing Rust code snippets in the markdown files on the website." +description = "Crate for testing Rust code snippets in markdown files on the website." edition = "2021" diff --git a/website/doctests/src/lib.rs b/website/doctests/src/lib.rs index ee400c52..f575fc23 100644 --- a/website/doctests/src/lib.rs +++ b/website/doctests/src/lib.rs @@ -1,4 +1,4 @@ -//! Crate for testing Rust code snippets in the markdown files on the website. +//! Crate for testing Rust code snippets in markdown files on the website. #[cfg(doctest)] // We use a bunch of Vitepress-specific syntax in the doctests, for example to diff --git a/website/src/changelog.md b/website/src/changelog.md index b804ef57..88ce1f3f 100644 --- a/website/src/changelog.md +++ b/website/src/changelog.md @@ -189,7 +189,7 @@ See the [blog post for this release](https://bon-rs.com/blog/bon-builder-v2-1-re ### Docs - Add a new section ["`None` literals inference"](https://bon-rs.com/guide/patterns/into-conversions-in-depth#none-literals-inference) to docs for "Into Conversions In-Depth" -- Fix the docs about the comparison of Into conversions on the ["Alternatives"](http://bon-rs.com/guide/alternatives) page that were not updated during the v2 release +- Fix the docs about the comparison of Into conversions on the ["Alternatives"](https://bon-rs.com/guide/alternatives) page that were not updated during the v2 release ### Fixed diff --git a/website/src/guide/alternatives.md b/website/src/guide/alternatives.md index a8d5d8ac..48d76f17 100644 --- a/website/src/guide/alternatives.md +++ b/website/src/guide/alternatives.md @@ -154,7 +154,7 @@ The chances of hitting a wall with function builders are close to zero, and even ## Generated Docs Comparison -Here is a table that compares the `rustdoc` output for builders generated by different crates based on different syntax. Click on the `source` links on the docs pages to see the original source code. +Here is a table that compares the `rustdoc` output for builders generated by different crates based on different syntax. | Underlying syntax | `bon` | `buildstructor` | `typed-builder` | `derive_builder` | | ----------------- | -------------------- | ----------------- | ----------------- | ----------------- | @@ -170,7 +170,7 @@ Here is a table that compares the `rustdoc` output for builders generated by dif [method-bon]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/methods/bon/ [method-bs]: https://docs.rs/bon-sandbox/latest/bon_sandbox/docs_comparison/methods/buildstructor/ -All builders were configured to produce roughly similar builder API. The notable exceptions are: +All builders were configured to produce roughly similar builder APIs. The notable exceptions are: - `buildstructor` doesn't support `#[builder(default)]` and `#[builder(into)]`-like annotations; - `buildstructor` doesn't support doc comments on function arguments; diff --git a/website/src/guide/benchmarks/compilation.md b/website/src/guide/benchmarks/compilation.md index d864d642..a12fa6ba 100644 --- a/website/src/guide/benchmarks/compilation.md +++ b/website/src/guide/benchmarks/compilation.md @@ -42,9 +42,9 @@ This is also done to reduce the builder's type signature size and reduce generic ### Can `bon` improve compile times? -Definitely, but it comes at a cost 🪙. `bon` prioritizes the convenience of the generated builder API, documentation cleanness, and the level of compile-time checks. +Definitely, but it comes at a cost 🪙. `bon` prioritizes the convenience of the generated builder API, documentation cleanness, and higher level of compile-time checks by default. -If you'd like to improve your compile times, consider disabling compile-time checks for overwrites of optional members in setters with [`#[builder(overwritable)]`](../../reference/builder/member/overwritable). However, don't rush with that, think carefully about the trade you would make. +If you'd like to improve your compile times, consider disabling compile-time checks for overwrites of optional members in setters with [`#[builder(overwritable)]`](../../reference/builder/member/overwritable). However, don't rush with that, think carefully about the tradeoff you would make. ### Why `derive_builder` is fastest to compile? @@ -74,4 +74,4 @@ The benchmarks were run on a dedicated root server `AX51-NVMe` on [Hetzner](http The source code of the benchmarks is [available here][benchmarks-source]. -[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/runtime +[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/compilation diff --git a/website/src/guide/benchmarks/runtime.md b/website/src/guide/benchmarks/runtime.md index 07369456..bcb7d908 100644 --- a/website/src/guide/benchmarks/runtime.md +++ b/website/src/guide/benchmarks/runtime.md @@ -74,4 +74,4 @@ The benchmarks were run on a dedicated root server `AX51-NVMe` on [Hetzner](http The source code of the benchmarks is [available here][benchmarks-source]. -[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/compilation +[benchmarks-source]: https://github.com/elastio/bon/tree/master/benchmarks/runtime