-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
resolve: Support custom attributes when macro modularization is enabled #53053
Conversation
r? @varkor (rust_highfive has picked a reviewer for you, use r? to override) |
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.
Looks great to me, thanks! Just one suspicious thing I'd like to clarify before r+'ing, and otherwise I got tripped up in a few places due to my own lack of in-depth understanding of resolve, so a few minor requests for comments!
src/libsyntax/ext/expand.rs
Outdated
@@ -1504,7 +1489,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { | |||
}; | |||
|
|||
if attr.is_some() || !traits.is_empty() { | |||
if !self.cx.ecfg.macros_in_extern_enabled() { | |||
if !self.cx.ecfg.macros_in_extern_enabled() && | |||
!self.cx.ecfg.custom_attribute_enabled() { |
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 wasn't quite able to discern why this change was needed, you can probably help me out though?
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.
Macros on foreign items are feature gated, and in this place custom attributes look like macro attrs, so without this condition they start requiring feature(macros_in_extern)
as well.
I should probably move feature gate checking for feature(macros_in_extern)
to some other place in which attribute resolution is already known and we can gate macros, but not other attributes.
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.
Ok sounds good to me!
@@ -565,7 +548,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { | |||
_ => unreachable!(), | |||
}; | |||
|
|||
attr::mark_used(&attr); | |||
if let NonMacroAttr { mark_used: false } = *ext {} else { |
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.
Could a small comment be added here as to why everything else other than this one case gets a mark_used
?
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.
Because everything except for NonMacroAttr
is a macro that's actually expanded and thus used in the process and NonMacroAttr { mark_used: true }
gets mark_used
because, well, it says so.
// under us. If this is the case we're making progress so we | ||
// want to flag it as such, and we test this by looking if | ||
// the `attr_id()` method has been changing over time. | ||
if invoc.attr_id() != attr_id_before { |
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.
Definitely glad to be rid of this, nice refactoring!
let path = invoc.path().expect("no path for non-macro attr"); | ||
match attr_kind { | ||
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper | | ||
NonMacroAttrKind::Custom if is_attr_invoc => { |
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'm not personally 100% familiar with resolve, so I'm a little lost here as to why if is_attr_invoc
is needed here. Could a comment be added about why it's here and why we'd have a non-attr invocation get resolved to a NonMacroAttr
def still?
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.
Anything in macro namespace can resolve to Def::NonMacroAttr
!
let x = inline!(); // ERROR expected a macro, found built-in attribute
src/librustc_resolve/macros.rs
Outdated
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom), | ||
ty::Visibility::Public, ident.span, Mark::root()) | ||
.to_name_binding(self.arenas); | ||
Ok(MacroBinding::Global(binding)) |
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.
To confirm, this basically means that it's impossible for an attribute to be "unresolved" now, right? All attributes that otherwise fail to get resolved simply get classified as "this is a custom attribute, it needs #![feature(custom_attributes)]
"?
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.
it's impossible for an attribute to be "unresolved" now
It's possible in some rare cases when import resolution/expansion is stuck due to indeterminacy, but otherwise yes, for a single-segment attribute you always get a custom attribute instead of "no resolution" (i.e. the old pre macro modularization behavior is restored).
@@ -8,21 +8,21 @@ | |||
// option. This file may not be copied, modified, or distributed | |||
// except according to those terms. | |||
|
|||
#![feature(tool_attributes)] | |||
#![feature(tool_attributes, custom_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.
Oh one thing I was wondering, this feature was just added to test that #[rustfmt]
, typically illegal under #![feature(tool_attributes)]
, is in fact actually allowed with #![feature(custom_attributes)]
?
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.
Yes, rustfmt
resolves to a tool module in type namespace, but it resolves to nothing in macro namespace and is thus interpreted as a custom attribute.
Unfortunately, feature gate errors are fatal and stop compilation for some reason, so I had to enable the feature to get other errors, which are reported later.
I should fix this some day.
I wasn't quite able to pintpoint where the single-segment clause was here in the resolver, could a test perhaps be added showing that the error for |
"lexical" in I'll add comments/asserts/tests for all the review stuff. |
Ok this all sounds great to me! r=me w/ the extra comments/tests |
@bors r=alexcrichton |
📌 Commit 3456bec178b159fc03e064dcb9cebef5384fdd84 has been approved by |
⌛ Testing commit 3456bec178b159fc03e064dcb9cebef5384fdd84 with merge 0da4190b512e0ff0610f0c0893f77be11c8ce7e6... |
💔 Test failed - status-appveyor |
One pretty-printing test is failing, will fix. |
…tures is enabled Do not mark all builtin attributes as used when macro modularization is enabled
Adjust a few fulldeps and pretty-printing tests Fix rebase
📌 Commit 5088611 has been approved by |
⌛ Testing commit 5088611 with merge 7a6e62234d1d22af99e101c0aa45148e9abb5aa4... |
💔 Test failed - status-travis |
This comment has been minimized.
This comment has been minimized.
@bors retry travis-ci/travis-ci#9696
|
resolve: Support custom attributes when macro modularization is enabled Basically, if resolution of a single-segment attribute is a determined error, then we interpret it as a custom attribute. Since custom attributes are integrated into general macro resolution, `feature(custom_attribute)` now requires and implicitly enables macro modularization (`feature(use_extern_macros)`). Actually, a few other "advanced" macro features now implicitly enable macro modularization too (and one bug was found and fixed in process of enabling it). The first two commits are preliminary cleanups/refactorings.
☀️ Test successful - status-appveyor, status-travis |
📣 Toolstate changed by #53053! Tested on commit ffb09df. 💔 clippy-driver on windows: test-pass → build-fail (cc @Manishearth @llogiq @mcarton @oli-obk, @rust-lang/infra). |
Tested on commit rust-lang/rust@ffb09df. Direct link to PR: <rust-lang/rust#53053> 💔 clippy-driver on windows: test-pass → build-fail (cc @Manishearth @llogiq @mcarton @oli-obk, @rust-lang/infra). 💔 clippy-driver on linux: test-pass → build-fail (cc @Manishearth @llogiq @mcarton @oli-obk, @rust-lang/infra). 💔 rls on windows: test-pass → build-fail (cc @nrc, @rust-lang/infra). 💔 rls on linux: test-pass → build-fail (cc @nrc, @rust-lang/infra).
on it |
Update clippy submodule r? @kennytm fixes breakage from #53053 (comment)
Note RLS's failure is different from clippy.
|
With this change I get:
the relevant imports seem to be:
and some more context for the error:
Given this is an issue using Serde, I fear this may affect many users once it hits nightly. Is this intentional? Any idea how to fix? |
cc #53144 |
@nrc It should be fixable and it must be fixed before #50911 is landed, so I'll send a PR in a few days. The workaround is to avoid |
Thanks @petrochenkov ! |
Basically, if resolution of a single-segment attribute is a determined error, then we interpret it as a custom attribute.
Since custom attributes are integrated into general macro resolution,
feature(custom_attribute)
now requires and implicitly enables macro modularization (feature(use_extern_macros)
).Actually, a few other "advanced" macro features now implicitly enable macro modularization too (and one bug was found and fixed in process of enabling it).
The first two commits are preliminary cleanups/refactorings.