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

Declare/forward struct and field-level attributes to builder #90

Closed
TedDriggs opened this issue Apr 25, 2017 · 0 comments
Closed

Declare/forward struct and field-level attributes to builder #90

TedDriggs opened this issue Apr 25, 2017 · 0 comments

Comments

@TedDriggs
Copy link
Collaborator

Issue #43 enables crate authors to derive additional traits on their builders. Some popular crates - specifically serde and diesel use attributes to control the output of their proc macros. This ticket explores ways to enable placing those attributes on the fields of the generated builder.

This ticket is meant for discussion, as there is not clear consensus on the subject.

Rationale

There have been questions about whether field-level attributes for other derived traits constitute too much complexity in a generated struct, and if a hand-written struct is more appropriate for these cases (see #80).

My contention (see #79) is that a generated struct cannot get out of sync with its base, unlike a handwritten struct that tries to shadow the base. For me, this creates a strong incentive to pursue generated code whenever the author's intention is "a struct with optional versions of whatever fields are in Foo".

In practice, the ability to deserialize into a builder makes validation for web services written with hyper or rocket (or any other library) much easier: Missing fields can be addressed as an application-layer business logic problem, rather than a deserialization failure.

Explorations

In prototyping this feature, I've come across two scenarios:

  1. An attribute present on the base struct's field needs to be present on the corresponding builder field. For example, #[serde(rename = "ipsum")]
  2. An attribute is needed on the builder struct field that is incorrect or invalid on the base struct. For example, a base struct that derives neither Serialize nor Deserialize cannot have the serde attribute appear on its fields.

Forcing solution 2 on case 1 is decidedly sub-optimal, as it opens the door to the same copy-paste errors that deriving the struct seeks to avoid - I made such copy-paste errors during my prototyping. Forcing solution 1 on case 2 can result in compile errors.

Proposal

  1. You can use #[builder(forward_attr(serde,...)] at the struct or field level to forward attributes with the same name to the builder. This is inherited, like setter(into).
  2. You can use #[builder_attr(serde(skip_serializing_if="Option::is_none"))] at the struct or field level to declare an attribute which will appear in the corresponding location on the generated builder. This is deliberately its own top-level attribute both for readability and to avoid any possible conflicts with future attributes the builder itself might want to expose.

Note: Unlike the allow, cfg, and doc attributes, these manually-forwarded attributes will not be applied to the generated setter. Proc macros on stable cannot do anything with inherent or trait methods, so applying these attributes there would be a compile error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants