Re-port lint attributes to attribute parsers#155691
Re-port lint attributes to attribute parsers#155691Bryntet wants to merge 3 commits intorust-lang:mainfrom
Conversation
|
Some changes occurred in compiler/rustc_attr_parsing cc @jdonszelmann, @JonathanBrouwer These commits modify the If this was unintentional then you should revert the changes before this PR is merged. Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_hir/src/attrs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
|
Just a sanity check |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@rust-timer build a8bd7ef |
This comment has been minimized.
This comment has been minimized.
| #![attr = Feature([fn_delegation#0])] | ||
| extern crate std; | ||
| #[attr = PreludeImport] | ||
| use std::prelude::rust_2021::*; |
There was a problem hiding this comment.
Why doesn't HIR pretty printing respect the comment ordering anymore?
| original_name: Option<Symbol>, | ||
| /// Index of this lint, used to keep track of lint groups | ||
| lint_index: usize, | ||
| kind: LintAttrTool, |
There was a problem hiding this comment.
Any specific reason to make the fields here private and provide trivial accessor methods instead?
Most of the other data in this file is public.
There was a problem hiding this comment.
I mainly just don't want other places constructing LintInstance without using LintInstance::new
I'm fine with making these public though if you think this would be preferable!
| None => LintAttrTool::NoTool, | ||
| }; | ||
|
|
||
| Self { original_name, span, lint_index, lint_name, kind } |
There was a problem hiding this comment.
Could you avoid using Self in non-generic contexts? At least in constructors like this.
There was a problem hiding this comment.
would you prefer this in the function signature as well?
There was a problem hiding this comment.
Up to you, I think having LintInstance { and LintInstance::new constructors searchable is particularly important, but I personally usually avoid Self in other cases too.
|
I'd like to review this PR before it is merged. The PR is huge and contains both various refactorings (registered_tools, early.rs, string -> symbol, etc) and the core change (migrating lint attributes), and perhaps some post-migration cleanups too. Also cjgilllot left some comments in #152369, didn't check if they were addressed yet. |
|
Finished benchmarking commit (a8bd7ef): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -0.0%, secondary 1.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 2.9%, secondary 4.3%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 490.734s -> 492.119s (0.28%) |
|
Reminder, once the PR becomes ready for a review, use |
803cb3c to
1a81a4b
Compare
| fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) { | ||
| // Warn on useless empty attributes. | ||
| // FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute` | ||
| let note = if attr.has_any_name(&[sym::feature]) |
There was a problem hiding this comment.
Why is this unused check for feature added here?
There was a problem hiding this comment.
diff looks weird, but it's because I refactored the check_lint_attr logic out of the already existing function check_unused_attribute
There was a problem hiding this comment.
I can't find this check anywhere in the old code tho, could you point me to where this check was moved from?
| /// context, through which all attributes can be lowered. | ||
| pub struct AttributeParser<'sess, S: Stage = Late> { | ||
| pub(crate) tools: Vec<Symbol>, | ||
| pub(crate) tools: Option<&'sess FxIndexSet<Ident>>, |
There was a problem hiding this comment.
Could you make this change to tools a separate PR that is merged before this one, to reduce the size of this one a bit?
There was a problem hiding this comment.
I'd rather move all the other refactorings too #155691 (comment), so the core change becomes as minimal as possible.
| } | ||
| } | ||
| false | ||
| self.tcx.hir_attrs(id).iter().any(Attribute::has_span_without_desugaring_kind) |
There was a problem hiding this comment.
This looks like it might partially fix #143094 (for the attrs that has_span_without_desugaring_kind supports)
- Does it?
- Why does this change need to be in this PR?
There was a problem hiding this comment.
I created the helper function has_span_without_desugaring_kind because if you don't do this check in a specific way, you'll get ICE, and the same check was done in multiple places, and it would become a big mess if we don't have a helper function
I think that issue could possibly be fixed by expanding on this helper function, it does not fix that specific issue right now, no.
| } | ||
| } | ||
| false | ||
| self.tcx.hir_attrs(id).iter().any(hir::Attribute::has_span_without_desugaring_kind) |
There was a problem hiding this comment.
Why this change?
There was a problem hiding this comment.
see my response to the comment above
This comment has been minimized.
This comment has been minimized.
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
| &mut emit_lint, | ||
| ); | ||
| } | ||
| let attr_id = sess.psess.attr_id_generator.mk_attr_id(); |
There was a problem hiding this comment.
This is not good, I'd rather make the attr_id in the context optional.
When processing lint attributes it is always set, so it can be unwrapped there.
|
|
||
| /// This method provides the same functionality as [`parse_limited_all`](Self::parse_limited_all) except filtered, | ||
| /// making sure that only allow-listed symbols are parsed | ||
| pub fn parse_limited_all_filtered<'a>( |
There was a problem hiding this comment.
Calling this function is not much simpler than calling the underlying parse_limited_all with an iterator.
If levels.rs calls it multiple times, then it could have a more specialized private helper, but otherwise it would probably be better to reduce the API surface.
| | [sym::deny] | ||
| | [sym::expect] | ||
| | [sym::forbid] | ||
| | [sym::warn] |
There was a problem hiding this comment.
What is the special relation between lint attributes and incorrect delimiters?
Why shouldn't the delimiters be reported for lint attributes specifically?
There was a problem hiding this comment.
it's specifically only in the case of when ShouldEmit::Nothing
when we compile a file, the the pre ast expansion linting pass doesn't care about cfg attrs
the only attributes we ever parse during pre ast expansion linting, are the lint attributes
because of the fact that in pre expansion, the lint attrs have the ShouldEmit::Nothing, so that we don't get duplicate error emissions, but since we don't know whether the attribute will actually be checked by later steps, (attribute could be removed by cfg), and the behaviour of ShouldEmit::Nothing.emit_err() is to delay_bug, which leads to a delayed bug which never errors and therefore we get ICE, see issue #154800
I want to make another PR later, making this cleaner, where we add maybe another variant to ShouldEmit that doesn't delay bugs or emit errors
|
|
||
| pub(crate) trait Lint { | ||
| const KIND: LintAttributeKind; | ||
| const ATTR_SYMBOL: Symbol = Self::KIND.symbol(); |
There was a problem hiding this comment.
Is ATTR_SYMBOl ever overridden to something other than Self::KIND.symbol()?
If not, then it shouldn't be a trait item.
I'm not actually sure why lint attribute kinds need to exist at type level (as opposed to value level LintAttributeKind enum).
There was a problem hiding this comment.
Is ATTR_SYMBOl ever overridden to something other than Self::KIND.symbol()?
If not, then it shouldn't be a trait item.
will change this
I'm not actually sure why lint attribute kinds need to exist at type level (as opposed to value level LintAttributeKind enum).
Because lints behave differently depending on the order lint attributes were placed on a target,
#[deny(unused)]
#[allow(unused)]
fn (my_var: bool) {
}gives different output compared to
#[allow(unused)]
#[deny(unused)]
fn (my_var: bool) {
}and unless we want to add an index number to each variant (only possible by being parsed by the same AttributeParser), and then also add support for AttributeParser::finalize to return multiple different AttributeKind as well as re-sorting the attributes into correct order
alternatively, you could keep the parsers separate, and sort them based on their span location, everytime you want to use them, but as you noted in a different comment, we shouldn't use spans for this, and it's innefficient.
|
|
||
| fn finalize(mut self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { | ||
| if !self.lint_attrs.is_empty() { | ||
| // Sort to ensure correct order operations later |
There was a problem hiding this comment.
Span ordering shouldn't generally be relied upon for anything besides displaying diagnostics.
There was a problem hiding this comment.
Just tested and this sort actually isn't necessary, which is nice :)
| &[] | ||
| } | ||
| fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) { | ||
| walk_list!(cx, visit_attribute, self.1); |
There was a problem hiding this comment.
I'm not sure what this change achieves.
Pre-expansion lints never want to check node attributes?
| } | ||
|
|
||
| pub fn set_lint_index(&mut self, new_lint_index: Option<u16>) { | ||
| pub fn set_lint_index(&mut self, new_lint_index: u16) { |
There was a problem hiding this comment.
This method is never used now.
get_lint_index isn't used either.
|
☔ The latest upstream changes (presumably #155662) made this pull request unmergeable. Please resolve the merge conflicts. |
Because clippy otherwise manually parses the level from the AST in multiple places |
Can we fix that in a separate PR, and just let clippy do that for now? |
change field `tools` on `AttributeParser` to hold `&'tcx RegisteredTools` Makes tools actually stored, and not just tool names this was originally part of rust-lang#155691 but was split out to make that PR smaller. r? @petrochenkov cc @JonathanBrouwer
change field `tools` on `AttributeParser` to hold `&'tcx RegisteredTools` Makes tools actually stored, and not just tool names this was originally part of rust-lang#155691 but was split out to make that PR smaller. r? @petrochenkov cc @JonathanBrouwer
change field `tools` on `AttributeParser` to hold `&'tcx RegisteredTools` Makes tools actually stored, and not just tool names this was originally part of rust-lang#155691 but was split out to make that PR smaller. r? @petrochenkov cc @JonathanBrouwer
Rollup merge of #156091 - Bryntet:move-tools, r=JonathanBrouwer change field `tools` on `AttributeParser` to hold `&'tcx RegisteredTools` Makes tools actually stored, and not just tool names this was originally part of #155691 but was split out to make that PR smaller. r? @petrochenkov cc @JonathanBrouwer
View all comments
I managed to fix the related issues related to the lint attrs PR (one of which, with the help of @JonathanBrouwer ❤️ )
this is another attempt at #152369 and reverts #155056
r? @JonathanBrouwer
r? @jdonszelmann
follow up to this PR would be a cleaner way to do what I do in the commit c9e832c
probably by adding a new variant to
ShouldEmitor changing theNothingvariant to have an option of whether to emit bugs or not