You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
An attribute present on the base struct's field needs to be present on the corresponding builder field. For example, #[serde(rename = "ipsum")]
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
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).
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.
The text was updated successfully, but these errors were encountered:
Issue #43 enables crate authors to derive additional traits on their builders. Some popular crates - specifically
serde
anddiesel
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
orrocket
(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:
#[serde(rename = "ipsum")]
Serialize
norDeserialize
cannot have theserde
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
#[builder(forward_attr(serde,...)]
at the struct or field level to forward attributes with the same name to the builder. This is inherited, likesetter(into)
.#[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
, anddoc
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.The text was updated successfully, but these errors were encountered: