Repository navigation
[nightly regression] rustc incorrectly parses attributes as macro invocations in nightly-2018-08-18 #53583
Description
Activity
- changed the title
[-][nightly regression] rustc incorrectly parses attributes as macro invocations in nighlty-2018-08-18[/-][+][nightly regression] rustc incorrectly parses attributes as macro invocations in nightly-2018-08-18[/+]on Aug 22, 2018 - addedA-resolveArea: Name/path resolution done by `rustc_resolve` specificallyArea: Name/path resolution done by `rustc_resolve` specificallyA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.Performance or correctness regression from stable to nightly.
on Aug 22, 2018 Currently this is expected behavior - fn-like macros, attribute macros and derive macros share single namespace and can shadow each other (similarly to types being able to shadow traits etc).
See #53205 (comment) for some motivation.This change shouldn't affect stable Rust since attribute macros were stabilized only few days ago.
Reacted by Eduard-Mihai Burtescu and Mazdak Farrokhzad... fn-like macros, attribute macros and derive macros share single namespace and can shadow each other (similarly to types being able to shadow traits etc).
Ok, but how is this
#[dummy("aaa")]a "attribute macro" instead of just an fn-like attribute? My understanding is that in order for it to be an attribute macro it should read#[dummy!("aaa")], no?@jchlapinski can you say a bit more about the actual code that is breaking for you?
cc @rust-lang/lang
- addedT-langRelevant to the language teamRelevant to the language team
on Aug 23, 2018 Flagging this for @rust-lang/lang discussion -- do we want all
macro_rulesand other macros to be usable as macros in attribute position? It's certainly something we've talked about, but I thought it'd be good to "check in" on this.In particular, if this is regressing code, it may not be something we can't really do. (Especially stable code -- it's still not clear to me just what the regressed code looks like.)
The error message seems a bit confusing as I think it leads the user to believe that
dummywas called inside the attribute (so it would have been expanded to#[println!("dummy: {}", "text")].If you actually wanted that behavior then the invocation should have been
#[dummy!("text")]which may be useful for some sort of attribute-aliasing. However; I think such a step would require some more thinking into the design and possible alternatives, etc.However, I think @petrochenkov's reasoning is right; this is not a stable-to-nightly regression because attribute macros were not previously stable. If you use an attribute name with the same name as amacro_rulesmacro, then the compiler is not to blame here imo.See #53583 (comment) for why it is a stable-to-nightly-regression. @petrochenkov's solution seems like a good one provided that attribute proc macros can be renamed to deal with conflicts.
@nikomatsakis basically we have custom derive for our diagnostic type trait
Diag, which is using an fn-like attribute nameddiagand also a macro (defined withmacro_rules) with that same name. Macro is for instantiation of out diagnostic type, where we do some backtrace generation, logging, etc.Now we can of course change either name, however I still do not understand why using same name for attribute AND a macro would clash? By that same logic I can have a field and a method with the same name, since field access and method calls are easily discerned in parsing. Is there a different way to expand a macro, without suffixing macro name with a
!?@Centril I am not blaming, I am just reasoning on why those things are sharing the same namespace. In my mind an attribute is something completely different than a macro. same logic for fields and methods as in my comment above.
@Centril I am not blaming, I am just reasoning on why those things are sharing the same namespace.
Oh; I didn't mean that you are blaming the compiler devs for breaking your code or something,
just that I don't think there has been breakage of our stability promises in this case :)basically we have custom derive for our diagnostic type trait Diag, which is using an fn-like attribute named diag and also a macro (defined with macro_rules) with that same name.
Ah, I see this is an inert attribute white-listed by a derive macro, not an attribute macro.
Then this is indeed a regression affecting stable.My preferred solution would be to increase priority of derive helper attributes during resolution (item 6 in #50911 (comment)), rather than introducing more namespaces.
macro diag() {} #[derive(Diag)] // introduces inert attribute `diag` into scope that shadows `diag`s from outer scopes #[diag] // refers to the inert attribute struct S;Reacted by Mazdak Farrokhzad@petrochenkov In short, thanks, that solution would solve our problem, and of course it is one way to do it.
But please, if I could take a few more minutes of Your time, explain why You keep referring to attributes, written as
#[attribute(...)]as "attribute macros"? Are those really "macros" in rust? A macro is something that gets expanded into code in place it is invoked (with!), exactly asmacro_rulesdefined macros work. An attribute is just an annotation without any inherent influence on the executable code, unless something will use that annotation to generate some code (like for example custom derive). As such those thing (attributes and macros) are completely different and should not shadow one another in any way, regardless whether macros can be expanded in attributes or not. Am I missing something?@petrochenkov Nevermind, please ignore. The magic name "inert attribute" have provided me with some results to read on. Thanks
@jchlapinski I know you said ignore, but I'll just expand briefly ;) in short, yes, we are aiming to allow macros to be used in those positions which would edit or alter the struct definition and expand it.
#[derive]is one such macro, but it happens to not modify the struct definition but rather just produce extra items alongside (impls, specifically). Think "decorators" in Python, in any case.That said, I myself am not entirely clear on the current contours of this design. So perhaps I will pose a few questions that I would like clarified:
- can you actually use a macro-rules macro in this position, or is it an error if a decorator resolves to a macro-rules macro?
- presumably proc macros can be used
- can macros beyond derive macros add these "whitelisted attributes"?
- can you actually use a macro-rules macro in this position, or is it an error if a decorator resolves to a macro-rules macro?
do we want all macro_rules and other macros to be usable as macros in attribute position?
No, I don't think so. The two kinds of macros have different 'signatures' so whether decl or proc, they have to be used differently. However, they do share the same namespace.
can you actually use a macro-rules macro in this position, or is it an error if a decorator resolves to a macro-rules macro?
"This position" is item position? In which case it should be fine. I believe with new proc macros there is no distinction between decorators and modifiers, and I don't care either way about old proc macros.
can macros beyond derive macros add these "whitelisted attributes"?
I believe this is currently a special attribute of derive macros. Real proc macros have more power since they consume the input to the macro, they can decide what to allow or disallow.
Reacted by Vadim PetrochenkovFixed in #54069
visited for triage. Seems under control from looking at PR #54069. P-high.
- added a commit that references this issue
on Sep 14, 2018
In the newest nightly all attributes with names identical to existing macros are parsed as macro invocation (note the lack of
!at the front ofdummyin the example below).Previous version
nightly-2018-08-17works as expected.This breaks compilation of some of our custom derives, using same name for attributes and macros, which was previously allowed.
I tried this code:
I expected this to complain about unknown custom attribute
dummyInstead, I got this error:
Meta
rustc --version --verbose: