Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom fields in the builder struct #245

Merged
merged 72 commits into from Apr 20, 2022

Conversation

ijackson
Copy link
Contributor

In Arti, we want our builder structs to sometimes contain particular types that we specify, other than Option<TargetFieldType>. This will allow us to control what the [De]serialize of the builder looks like.

There are a number of other conceivable uses for this escape hatch. The internal machinery to implement this could also be used for other feature(s).

@TedDriggs
Copy link
Collaborator

FYI, given the size of this PR I probably won't be able to get to it until next week.

@ijackson
Copy link
Contributor Author

FYI, given the size of this PR I probably won't be able to get to it until next week.

Sure, thanks for the update. FYI I will be away next week, so I will hope to read your thoughts when I get back. I hope you find my structuring into individual commits helpful.

Copy link
Collaborator

@TedDriggs TedDriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quality work. I'm on the fence about whether this pushes derive_builder too far into the realm of arbitrary code generation - or if there's a way to unbundle what derive_builder does such that these advanced scenarios feel like composition rather than ever-deeper modification.

derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/initializer.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/parsed_literal.rs Outdated Show resolved Hide resolved
@ijackson
Copy link
Contributor Author

This is quality work. I'm on the fence about whether this pushes derive_builder too far into the realm of arbitrary code generation - or if there's a way to unbundle what derive_builder does such that these advanced scenarios feel like composition rather than ever-deeper modification.

Thanks for the review. I need to read the details again properly to get to grips with things (and remind myself of the structure...)

I too find the shape of this escape hatch rather uncomfortable. It's not super convenient and the syntax is awkward. But I think it is necessary precisely to enable composition: allowing the user to insert arbitrary fields into the builder structure, thus letting the user compose autogenerated code from derive_builder with their own handling of special cases. The new plumbing in derive_builder is close to the minimum necessary to make that work.

I considered whether it woudl be possible to allow adding fields to the builder without any corresponding field in the output structure; but that would involve smuggling the whole definition of a field through magic attributes. Or providing an attribute macro, which can of course filter the input arbitrarily. I didn't like either of those ideas.

ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 13, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 13, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 13, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 13, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 13, 2022
As per
  colin-kiegel#245 (comment)

This may yet go away (or something), apropos further review comments.
@ijackson
Copy link
Contributor Author

I think I've dealt with all your comments now. There are several where I think your further opinion is needed; the others I have marked "resolved". Thanks.

@ijackson ijackson requested a review from TedDriggs April 13, 2022 13:41
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
.as_expressed_vis()
.or_else(|| self.parent.field.as_expressed_vis())
.unwrap_or(Visibility::Inherited)
if !self.field_enabled() {
Copy link
Collaborator

@TedDriggs TedDriggs Apr 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this now preempt the #[builder(field(...))] visibility settings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a comment about this. This preserves the behaviour from before my MR. Previously this private visibility was dealt with in ad-hoc code in the builder struct code generator. Now, the field type comes from BuilderFieldType, and the code generator always uses the visibility which comes from field_vis, so field_vis must return the desired answer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First: Great comment.

Second: I agree with removing the ad-hoc hiding in codegen, so let's keep the logic for visibility all here.

Third: With #247, I feel like explicit field-level visibility should overrule the inferred visibility from being a phantom. How would you feel about this checking self.field.field.as_expressed_vis(), then checking if the field is enabled, then checking the struct-level? Or should it check those first with the normal inheritance chain and finally fall back to inferring Inherited vis if nothing is pushing to make it public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like explicit field-level visibility should overrule the inferred visibility

Good point. I agree completely. about explicitly-specified field-level visibility, But, I think, only field-level, not struct-level visibility.

derive_builder_core/src/setter.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Show resolved Hide resolved
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
Ie, abolish the nesting in custom().  Incidentally, this now makes it
possible to specify `build` without `type`.

As per
  colin-kiegel#245 (comment)
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
@ijackson
Copy link
Contributor Author

I am going to rebase this onto master now, to resolve the conflict. I won't make other changes as part of the rebase.

ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
As per
  colin-kiegel#245 (comment)

This may yet go away (or something), apropos further review comments.
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
Ie, abolish the nesting in custom().  Incidentally, this now makes it
possible to specify `build` without `type`.

As per
  colin-kiegel#245 (comment)
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
ijackson added a commit to ijackson/rust-derive-builder that referenced this pull request Apr 14, 2022
Copy link
Collaborator

@TedDriggs TedDriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting close now.

derive_builder/tests/builder_field_custom.rs Outdated Show resolved Hide resolved
derive_builder/tests/compile-fail/builder_field_custom.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/builder_field.rs Outdated Show resolved Hide resolved
derive_builder_core/src/initializer.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/setter.rs Show resolved Hide resolved
@ijackson ijackson requested a review from TedDriggs April 19, 2022 15:36
@ijackson
Copy link
Contributor Author

Thanks for the detailed review! I think I have dealt with all your comments.

Copy link
Collaborator

@TedDriggs TedDriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All substantive feedback is addressed; there are a couple minor changes and then we'll be ready to merge.

derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
derive_builder_core/src/macro_options/darling_opts.rs Outdated Show resolved Hide resolved
ijackson and others added 3 commits April 19, 2022 23:09
Co-authored-by: Ted Driggs <ted.driggs@outlook.com>
Co-authored-by: Ted Driggs <ted.driggs@outlook.com>
Co-authored-by: Ted Driggs <ted.driggs@outlook.com>
@ijackson
Copy link
Contributor Author

All substantive feedback is addressed; there are a couple minor changes and then we'll be ready to merge.

Cool, thanks. Your suggestions looked good to me so I just committed them via the github UI.

Copy link
Collaborator

@TedDriggs TedDriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ijackson what a heroic effort, and a great result.

I appreciate that you split your work out by commit, but I'd rather not add all 72 as individual commits to master. Would you like to do an interactive rebase locally to organize them, or would you prefer I squash and merge?

@ijackson
Copy link
Contributor Author

Thanks :-). I think it's probably best to squash, unless you would prefer to retain a more detailed history. If the latter, let me know.

@TedDriggs
Copy link
Collaborator

Squashing now

@TedDriggs TedDriggs merged commit df62582 into colin-kiegel:master Apr 20, 2022
This was referenced Apr 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants