Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upBuilt-in macros, derives and attributes have inconsistent interactions with macros of the same name. #52269
Comments
petrochenkov
self-assigned this
Jul 11, 2018
This comment has been minimized.
This comment has been minimized.
|
I'm going to implement roughly the same scheme as described here, because it's currently used for non-macro namespaces (I described it previously in the tool attributes RFC - rust-lang/rfcs#2103 (comment)).
If something currently diverges from this scheme, e.g. builtin something shadows user-defined something, then it's a bug and it should be reported (preferably in a separate focused issue with reproduction). The only tricky case here is attributes that need to be inspected before name resolution, like |
petrochenkov
referenced this issue
Jul 16, 2018
Merged
resolve: Modularize crate-local `#[macro_export] macro_rules` #52234
alexcrichton
added this to the Rust 2018 Preview 2 milestone
Jul 17, 2018
alexcrichton
added
the
A-macros-1.2
label
Jul 17, 2018
This comment has been minimized.
This comment has been minimized.
|
Currently attributes exist in another namespace so if we implement overriding of attributes it'll be a breaking change. Right now you can have both a |
This comment has been minimized.
This comment has been minimized.
|
My plan was to implement the principled scheme first, then run it through crater and look how much code breaks on stable, what cases of breakage are common, and then make adjustments. |
This comment has been minimized.
This comment has been minimized.
|
Sounds like a good plan. I've run into this issue while working on custom test frameworks so mind if I take a crack at it? |
This comment has been minimized.
This comment has been minimized.
|
@djrenren There's one piece of work that's relatively independent though. |
This comment has been minimized.
This comment has been minimized.
|
Sweet I'll take a look at it. |
petrochenkov
referenced this issue
Jul 30, 2018
Merged
resolve: Implement prelude search for macro paths, implement tool attributes #52841
Mark-Simulacrum
modified the milestones:
Rust 2018 Preview 2,
Rust 2018 RC
Jul 31, 2018
bors
added a commit
that referenced
this issue
Aug 1, 2018
Mark-Simulacrum
added a commit
to Mark-Simulacrum/rust
that referenced
this issue
Aug 1, 2018
bors
added a commit
that referenced
this issue
Aug 1, 2018
bors
added a commit
that referenced
this issue
Aug 2, 2018
aturon
modified the milestones:
Rust 2018 RC,
Edition RC 2
Sep 5, 2018
This comment has been minimized.
This comment has been minimized.
|
Bumping to RC2 milestone. |
This comment has been minimized.
This comment has been minimized.
|
@petrochenkov to check on on this issue, I think #53913 is evaluating the impact of one strategy for solving this, right? Otherwise I believe the built-in attributes cannot currently be shadowed, even if a macro of such a name is imported? (in that it looks like nightly accepts this:) #![feature(decl_macro)]
macro cfg() {
}
#[cfg(all())]
fn main() {} |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton |
petrochenkov
referenced this issue
Sep 5, 2018
Merged
resolve: Future proof resolutions for potentially built-in attributes #53913
bors
added a commit
that referenced
this issue
Sep 11, 2018
This comment has been minimized.
This comment has been minimized.
|
Status: future proofed in #53913. There's still a single macro namespace, but it has two sub-namespaces now to avoid backward-incompatible conflicts. #54069 has more detailed description of how the sub-namespace scheme works.
After #53913 if potentially built-in attribute is ambiguous with any other macro name in scope (taking sub-namespacing into account), then error is reported. It's possible to relax this restriction to achieve the end goal - user-defined attribute macros shadowing built-in attributes (or rather newly introduced built-in attributes not breaking user-defined macros), but it's not entirely trivial, see #53913 (comment) for more detailed explanation.
This artificial error is still in place, but it can be easily removed now since it doesn't serve its purpose of preventing user-defined derives from shadowing built-in derives. Future plans:
I think we can close this generic issue now and perhaps create new more focused issues for "future plans" (if those even need tracking). |
alercah commentedJul 11, 2018
•
edited
Macros currently occupy a single namespace, regardless of whether they are used for attributes, derives, or function-like macros. This was a design decision for procedural macros, on the basis that it is easier to split them into separate namespaces later, but it leads to some confusing interactions with built-in attributes (like
cfgorderive), macros (likecompile_errororenv) or derives (likeEqorClone). The behaviour should be tightened up so that it is intuitive and straightforward to explain.Currently, the rules appear to be as follows:
derivecan be called, or an attribute namedcompile_errorcan be used). Raw identifiers can be used to get around the built-in.proc_macro_derive. If a macro is defined with the same name as a built-in derive, it takes precedence. Defining a macro withproc_macro_derivethat conflicts with the built-in gives an error at the definition.If
use_extern_macrois enabled, then you can freely rename imports. This lets you get around theproc_macro_deriverule:Note that this behaviour applies only to built-in macros. Macros defined in libstd or libcore (for
no_std) are imported in the prelude and can be overridden as one would expect for prelude names.I do not think we can get away with treating all builtins as if they are normal names defined in the prelude that can be overridden. While it might be possible to treat some of them that way, the
cfgattribute is an excellent example of one that cannot be safely modified, or else the following program would be problematic, because macro imports apply throughout the entire source file, not just after the import:At the same time, I don't see why built-in derives should be special. The traits they implement are not, after all; even the ones like
Copywhich are magical. And it is possible, though inadvisable, to shadow them independently:trait Copy {}won't prevent#[derive(Copy)]from working, for instance.This implies to me that we should have the following in the macro namespace:
This would imply the following behaviour changes:
proc_macro_derivecan declare derives with the same name as an intrinsic derive; these will simply shadow the intrinsic.This leaves an unresolved question around renaming imports (e.g.
use foo::bar as cfg;wherefoo::baris names both a function and macro; is this an error? warning? or it just silently hides the macro asr#cfg?) but would clean up the bulk of the issues with the situation.