Skip to content

Expose the builder type publicly #8

@lilyball

Description

@lilyball

It looks like the generated code puts everything into a private module named after the builder type. For example, looking at the sample code from the README:

use makeit::Builder;

#[derive(Builder)]
struct Foo<'a, T: std::fmt::Debug> {
    bar: &'a T,
    #[default(42)]
    baz: i32,
}

This produces an expansion like

mod FooBuilderFields {
    pub struct FooBuilder<…> {}
    pub struct BarSet;
    pub struct BazSet;
    pub struct BarUnset;
    pub struct BazUnset;
    // impls …
}

And the generated documentation does not include the FooBuilder type:

screenshot of the generated documentation for Foo, in which the <Foo as Buildable>::Builder type is listed as FooBuilder but with no link to see the documentation for FooBuilder

If I know the module name I can write pub use FooBuilderFields::FooBuilder, but it feels like I shouldn't have to do that. The builder should just be available by default.

I can imagine a scenario in which someone might want to move the builder into a separate module, like pub mod builder { pub use super::FooBuilderFields::FooBuilder; } but that is a bit of an edge case and should require opt-in behavior.

Proposed behavior

The macro expansion should simply declare the FooBuilder type in the current module instead of inside the FooBuilderFields module, and it should mark it as pub if the decorated type itself is pub. Also see #7 in which I argue that the Buildable type should be removed and propose a #[builder(…)] attribute for renaming the builder() method and FooBuilder type as needed.

If I have an edge case where I want Foo to be public but I want the FooBuilder type to be moved into a different module, I can deal with that using existing visibility rules by writing something like:

mod foo {
    #[derive(makeit::Builder)]
    pub struct Foo<'a, T: std::fmt::Debug> {
        bar: &'a T,
        #[default(42)]
        baz: i32,
    }
}
pub use foo::Foo;
pub mod builder {
    pub use super::foo::FooBuilder;
}

I don't see any reason to make the BarSet/BarUnset/… types public by default so they can stay as they are.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions