-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Extend #[deriving(Default)] to support specified field defaults #14219
Conversation
Need to think about how this interacts with macro hygiene. |
I think it won't be a problem though as long as the macro expander keeps the identifiers at the same scope. |
In general, I agree. In this specific case, the expansion is done immediately after the |
I think this should be feature gated; because the use of strings seems unfortunate and the possible concerns about hygiene/resolution. |
ast::LitStr(ref s, _) => Some(cx.parse_expr(s.get().to_strbuf())), | ||
_ => { | ||
cx.span_err(v.span, | ||
"non-string literals are not allowed in #[default] attribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the convention is for backticks around "code".
@huonw Feature-gating suggests that there's some way it will become un-feature-gated at some point. But our attribute syntax doesn't allow for expressions as the value. If we change the attribute syntax that will presumably be a backwards-incompatible change anyway, so I don't see the danger in leaving this un-feature-gated. |
I don't think it is. It seems (relatively) reasonable for attributes to just allow arbitrary token trees, or even just the |
Perhaps. But unless there's any expectation that this will ever actually be done, feature-gating this functionality just serves to ensure nobody ever uses it. |
That is definitely hyperbolic: people do use feature gated things. |
People use feature-gated things when either they cannot do what they want without it, or it's sufficiently problematic to do what they want without it. But it's a lot less likely that someone will be willing to use a feature-gated string just to avoid writing an In any case, my point still stands that, unless we actually believe that we may change the attribute syntax to allow arbitrary token trees, then feature-gating this doesn't make sense. The only good reason to feature-gate it is so that making that change to attributes doesn't break anyone who's already using this feature. But unless we think we're actually going to make such a change, that reason doesn't apply. And if we feature-gate it now on the off chance that we decide to make that change later, then it will never get un-feature-gated (because it was based on a hypothetical, one that will remain possible indefinitely). |
I would be cautious about adding a feature such as this. We don't currently have any form of customizing #[deriving], and I fear that adding this would open up the floor for many more changes to come in. It's tough to see how all these deriving modes would interact and it would be a little unfortunate for structs to normally be littered with attributes for all the various behaviors they may want. The idea in general seems appealing, but it also doesn't seem that far off from just writing |
When deriving the Default trait, individual struct fields can be marked up with a `#[default="expr"]` attribute to indicate that this field should be given the results of `expr` instead of `Default::default()`. Example: #[deriving(Default)] struct Foo { #[default="42"] x: int, #[default="Ok(())"] err: IoResult<()> }
@alexcrichton I was under the impression that the ability to customize As for customizing the ability of existing
Sure, and the ability to write
I agree it's unfortunate, but the only real alternatives are to either allow arbitrary token streams in attributes, or to add syntax
I think the most compelling reason to do this is the fact that almost nothing uses The idea is that by lowering the amount of effort it takes to provide a |
I've pushed a new version based on @huonw's feedback. |
As an example of the point I just made, |
The list does not end with Default. This is not the only deriving mode which will have a request to be configured. |
All of those with the exception of Encodable/Decodable would require passing the field (or the entire struct) in to the expression. I don't see how to handle that, without doing something like Encodable/Decodable I didn't think of. And actually, I do want to do precisely that sort of thing. Go supports the ability to e.g. change the name of the field when encoding to JSON. It would be really convenient if Rust could do the same thing. This was even suggested recently in IRC. Although since it's actually a generic Encodable/Decodable that's implemented rather than specifically JSON support, I'd be really cautious about trying to do that. That said, the existence of |
I like this PR!
|
If merged un-feature-gated, then need to have a story for customizing all deriving modes, whether that be through these manual attributes or some other method. It doesn't sound like that story currently exists. |
@alexcrichton As discussed in #14268, I'm in favor of coming up with a solution for customizing all deriving modes. I'm going to close this PR for the time being, until we've come up with the answer to that. |
The `comparison_chain` lint might suggest code which seems less natural to beginners. [Discussion](https://rust-lang.zulipchat.com/#narrow/channel/257328-clippy/topic/demote.20some.20lints.20to.20.60pedantic.60) changelog: [`comparison_chain`]: change lint category to `pedantic`
When deriving the Default trait, individual struct fields can be marked
up with a
#[default="expr"]
attribute to indicate that this fieldshould be given the results of
expr
instead ofDefault::default()
.Example: