-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Attribute macro helper attributes #65823
Comments
This is not technically necessary because proc macro attributes can remove these attributes from their input unlike derives, but should be supportable pretty easily as a convenience feature once #64694 lands. |
Good point; I do think it would be useful for the language to do this automatically as an ergonomics thing from the POV of a macro author myself. Nominating based on @petrochenkov's comment to see what the preliminary interest is in the language team. We may or may not ask for an RFC based on the discussion. |
Can we clarify what the expected behavior is here? If you include I'm generally positive on the idea but would like to see a more complete write-up, at minimum. I mildly prefer a small RFC but I think a PR that links to a good write-up would probably suffice. (Presumably we would then create a tracking issue.) |
Is this always true? I just tried this with a proc macro attribute on a function, and the compiler attempted to expand the "helper" attribute and failed before the macro got a chance to strip it. In my scenario the helper attribute was placed on a statement in the function, if that makes any difference. |
@calebzulawski |
I just tried a minimal example and it worked as you describe, I imagine it's likely I wasn't properly stripping out the helper in my larger example. So is this safe behavior to rely on right now? Similar questions were asked in rust-lang/reference#578 and rust-lang/reference#692 but it doesn't look like there's a clear answer. Perhaps helper attribute syntax would be nice but I think documenting the behavior might go a long way. |
Having gone through and stumbled over this myself just recently (I actually thought adding a remark to the docs would make sense: rust-lang/reference#716) I must say I really think this needs no compiler support. Here are just a few simple lines (using the syn crate) that completely obliterate all attributes from the AST given to it: extrawurst/alpaca-rust@46dbba6#diff-8f097454b072a95a96c470f9c3f84c5fR136-R151 but that could easily be extended to just the attributes that you want to remove. |
This will make things easier when multiple attribute macros use the same helper attributes. With #[derive(Serialize,Deserialize)]
struct Foo {
#[serde(rename = "bar")]
x: i32
} And none of the derives has to worry that |
Any updates on this? |
I find stabilized rfc2565 which seems related to this issue. But I find no way to define
|
While technically true, this would mean, you can only have one proc_macro call, because you have no way of telling, if any of the other procmacro calls are the same macro as aliasing is a thing. |
Since 1.52 and #79078 I think this is no longer an issue: the primary attribute can strip out all helper attributes, with the sole restriction that helper attributes cannot appear before the primary attribute (this restriction also applies to This goes back to @nikomatsakis's comment:
This potential feature would now be the sole point of "helper attributes", but in my opinion it's just not necessary (to be useful, custom parsing code must match them anyway, so it might as well remove them from the output too). |
The issue arises when you need support for multiple calls to a Imagine a #[macro_x(some_options_here)]
#[macro_x(some_other_options_here)]
struct Test {
a: u8,
#[attr_y]
b: String,
} You can't just start stripping the field attributes, because the second call to #[macro_x(...)]
#[macro_x_crate::macro_x(...)]
#[re_export::macro_x(...)]
#[import_as_macro_x(...)] This ofc can be solved by just switching to #[derive(macro_x)]
#[macro_x(some_options_here)]
#[macro_x(some_other_options_here)]
struct Test {
a: u8,
#[attr_y]
b: String,
} Now both problems are fixed, helper attributes don't need to be stripped and This is just an example that can work with a |
Fair argument, though personally I don't agree. Your example uses But you can do the same with any type of proc macro preceeding the repeated attribute, e.g. #[my_proc_attribute_macro]
#[my_extra_attr(foo)]
#[my_extra_attr(bar)]
struct S; The only difference from |
The idea was to have multiple calls to a proc macro being able to read the same attributes without having to delete them. |
That's a pretty good motivation, IMO. |
@dhardy you are right that this is exactly the same as the
Basically what I would like is to have the ability to do this: #[my_proc_attribute_macro(foo)]
#[my_proc_attribute_macro(bar)]
struct S; Without a necessary line on top. |
@daxpedda actually, what you mean is the ability to have multiple uses of a single attribute which can observe other uses of that same attribute, and without the first instance doing the work of implementing all instances (which is also possible). Note that there was also an afore-mentioned point about paths and renaming of the macro import, which is still a potential issue here. |
The goal is
#[my_proc_attribute_macro(foo)]
#[my_proc_attribute_macro(bar)]
struct S {
#[helper(option)]
a: u8,
} The way to implement this, is to have
The reason this isn't possible, is because of
The solution to that problem is to replace multiple uses of a #[my_proc_attribute_macro]
#[my_proc_attribute_macro_helper(foo)]
#[my_proc_attribute_macro_helper(bar)]
struct S {
#[helper(option)]
a: u8,
} This avoids any pathing issues, because attribute helpers don't use paths. This still requires cleaning all helper attributes and is, from the point of view of syntactic effort, equivalent to: #[derive(my_proc_attribute_macro)]
#[my_proc_attribute_macro_helper(foo)]
#[my_proc_attribute_macro_helper(bar)]
struct S {
#[helper(option)]
a: u8,
} With the additional benefit of not requiring to clean up helper attributes. Of course this whole argument only makes sense when talking about using Not trying to argue against myself here. I would still like to see support for attribute helpers in |
What's stopping this from going forward? I think @daxpedda outlined it very well, it's useful in several situations and not that hard to implement. Tangentially, we shouldn't offload the problem upwards, i.e., expect syn to solve everything. The ergonomics of macro development are important. |
The reference states that custom derive macros support defined helper attributes:
However, the same does not appear to apply to
proc_macro_attribute
. Please extend it to do so.Motivation is limited, but this could provide simpler specification here.
Related: #53012
The text was updated successfully, but these errors were encountered: