-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Declarative macro_rules!
derive macros
#3698
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
base: master
Are you sure you want to change the base?
Declarative macro_rules!
derive macros
#3698
Conversation
6470058
to
a3cd084
Compare
Nominated as a follow-up to recent lang discussions about this. |
Since its call-side syntax is different from normal macro_rules! (i.e. The same to #3697 where we could name it |
One thing that would be really nice (i.e. greatly increase usability of decl macros) (though would not at all decrease the usefulness of this feature) is proper, full-featured parsing of meta fragments of decl macros. Right now, if you want to parse arguments to a decl macro in a MetaList form, you have to either enforce that the named arguments come in a specific order, or use a tt-muncher (and even then, it's not clear at first thought how you'd do it!). Obviously this is something that would introduce a whole new axis of complexity to decl macro declarations and evaluation, but being able to specify something like (Shoulda brought this up at the hopes and dreams for the language session at Unconf 🙃) |
@coolreader18 I would love to see many parsing improvements for macros, including something to address this kind of parsing difficulty. I don't think that's specific to derive or attribute macros, though it certainly makes them more useful. |
In order to avoid name collisions in helper attributes between different derives, I think it would be worth it to take a page out of serde here and require namespacing of those attributes. For example, simple serde code: #[derive(Debug, Deserialize)]
struct Message {
#[serde(rename = "type")]
type_: String,
#[serde(default = "Message::default_payload")]
payload: String,
} Some names (like Convention for the namespace could dictate that it be either a parent module/crate name, or the name of the trait, snake-cased. |
I don't think that's a good idea. It's already the case that other libraries than |
Perhaps some kind of |
There has also been talk of "common" attributes, like For clap, namespacing by crate or derive name was insufficient and it now processes 4 different namespaces. If we did encourage something by default, i think it should be derive name so there is a clear relationship. On a simlar note of constraining users, imo derives should only produce a trait impl for the derive and considered proposing that be enforced but figured that deviating for what proc-macros provide would also be a downside. Also, I've seen with clap how it can be useful to include mostly-internal trait impls with the requested one. |
Note that imposing such restriction would make it difficult to write derives that implement traits like I was recently exploring this space while working on |
I would note that I specifically mentioned "as a convention". If anything, the fact that I think enforcing namespacing and having a simple convention for simple usecases -- so folks can just follow along -- would work well. Perhaps a clippy lint which has to be explicitly
Common attributes are fine: a standardized meaning should not cause "mishaps". |
We discussed this briefly in today's planning meeting. Based on that discussion, I updated the Motivation section to include the concrete examples motivating this. I'm also going to restart the proposed FCP, since team membership has changed since it was previously started. @rfcbot cancel |
@joshtriplett proposal cancelled. |
@rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
Nominated for consideration in a meeting to address any questions that arise. |
It's not clear to me how this would work exactly. That mechanism works by replacing the built-in
The ones I see are crate-internal uses. That is a completely valid use case, but it raises a question for me. Do you think this is due to parsing limitations of declarative macros, the inconvenience of requiring users to use The motivation section might additionally benefit from reiterating some of the benefits of derives over attribute macros in general (since this is being considered alongside #3697). In particular, they work better with tools like rust-analyzer because the tool always knows the item that follows is a normal, valid item, without having to expand the macro. |
Hmmm, good point. I've moved this mention to future work, alongside the mention of having a way for derive macros to invoke other derive macros.
I would guess that in part it's the inconvenience and oddity of requiring And I agree. I don't think there are any dependencies between these RFCs; they just benefit from each other.
Done. |
Thanks @joshtriplett. The uses of @rfcbot reviewed |
@rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@rfcbot reviewed Thanks @joshtriplett for putting this forward. Nicely done. Everything I said in #3697 (comment) applies here as well. For our future selves, note that this RFC includes things that anticipate RFC #3715. That's OK, I think. I'd estimate that it's more likely than not that we do end up moving that one forward as well. |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
#[derive(Answer)] | ||
struct Struct; | ||
|
||
fn main() { | ||
let s = Struct; | ||
assert_eq!(42, s.answer()); | ||
} |
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.
nit: There seems to be a missed opportunity to have Universe::answer
by a thing here 🤔
#[derive(Answer)] | |
struct Struct; | |
fn main() { | |
let s = Struct; | |
assert_eq!(42, s.answer()); | |
} | |
#[derive(Answer)] | |
struct Universe; | |
fn main() { | |
let u = Universe; | |
assert_eq!(42, u.answer()); | |
} |
Many crates support deriving their traits with
derive(Trait)
. Today, thisrequires defining proc macros, in a separate crate, typically with several
additional dependencies adding substantial compilation time, and typically
guarded by a feature that users need to remember to enable.
However, many common cases of derives don't require any more power than an
ordinary
macro_rules!
macro. Supporting these common cases would allow manycrates to avoid defining proc macros, reduce dependencies and compilation time,
and provide these macros unconditionally without requiring the user to enable a
feature.
I've reviewed several existing proc-macro-based derives in the ecosystem, and
it appears that many would be able to use this feature to avoid needing proc
macros at all.
Rendered