-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix MissingDoc
quadratic behaviour
#98153
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
Fix MissingDoc
quadratic behaviour
#98153
Conversation
The `MissingDoc` lint has quadratic behaviour when processing doc comments. This is a problem for large doc comments (e.g. 1000+ lines) when `deny(missing_code)` is enabled. A 1000-line doc comment using `//!` comments is represented as 1000 attributes on an item. The lint machinery iterates over each attribute with `visit_attribute`. `MissingDoc`'s impl of that function calls `with_lint_attrs`, which calls `enter_attrs`, which iterates over all 1000 attributes looking for a `doc(hidden)` attribute. I.e. for every attribute we iterate over all the other attributes. The fix is simple: don't call `with_lint_attrs` on attributes. This makes sense: `with_lint_attrs` is intended to iterate over the attributes on a language fragment like a statement or expression, but it doesn't need to be called on attributes themselves.
They each have a single call site.
Here are some benchmarks that are outside of
|
I'm not expecting this to improve any of the benchmarks in rustc-perf, but let's double check: @bors try @rust-timer queue |
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
⌛ Trying commit be45f10 with merge 18823ac9b9380a53c4930484df17f531fc409671... |
☀️ Try build successful - checks-actions |
Queued 18823ac9b9380a53c4930484df17f531fc409671 with parent 1b9daa6, future comparison URL. |
Finished benchmarking commit (18823ac9b9380a53c4930484df17f531fc409671): comparison url. Instruction count
Max RSS (memory usage)Results
CyclesResults
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. @bors rollup=never Footnotes |
lint_callback!(cx, check_attribute, attr); | ||
}) | ||
fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) { | ||
lint_callback!(self, check_attribute, attr); |
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.
What happens if we have an allow(some lint about attributes)
followed by an attribute that triggers that lint?
Can we make sure we have the same behaviour whatever the position of those attributes (including expression, patterns...)?
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.
Can you give a more specific example? I know this change fixes the performance problem and passes all the tests, but I don't know enough about linting to know if there is some edge case that it will miss.
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.
Only clippy uses late lints on attributes. They should probably made early lints, and drop support for late lints on attributes.
For instance:
#[warn(macro_use_imports)]
#[macro_use]
extern crate std;
and with swapped 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.
Is attribute order supposed to be significant? Are attributes supposed to apply to other attributes on the same item, or do they just apply to the item? The latter makes more sense to me, but I honestly don't know.
They should probably made early lints, and drop support for late lints on attributes.
Sorry, I don't understand this. Is this an argument in favour of this PR's change, or against it, or is it orthogonal?
I tried your example, with this code (including slight necessary changes):
#[warn(clippy::macro_use_imports)]
#[macro_use]
extern crate std as other_std;
fn main() { }
With a standard rustc (not containing this PR's changes) I get much the same output from cargo clippy
regardless of the order of the attributes:
warning: unused `#[macro_use]` import
--> src/main.rs:2:1
|
2 | #[macro_use]
| ^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error: useless lint attribute
--> src/main.rs:1:1
|
1 | #[warn(clippy::macro_use_imports)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![warn(clippy::macro_use_imports)]`
|
= note: `#[deny(clippy::useless_attribute)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute
If I add the !
as suggested then the error goes away, unsurprisingly.
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.
Is attribute order supposed to be significant? Are attributes supposed to apply to other attributes on the same item, or do they just apply to the item? The latter makes more sense to me, but I honestly don't know.
For now, the order of attributes is not significant. My question is mostly: are we changing behaviour?
They should probably made early lints, and drop support for late lints on attributes.
Sorry, I don't understand this. Is this an argument in favour of this PR's change, or against it, or is it orthogonal?
This is rather orthogonal. I'll post a follow-up issue if you don't mind.
I tried your example, with this code (including slight necessary changes):
#[warn(clippy::macro_use_imports)] #[macro_use] extern crate std as other_std; fn main() { }With a standard rustc (not containing this PR's changes) I get much the same output from
cargo clippy
regardless of the order of the attributes:warning: unused `#[macro_use]` import --> src/main.rs:2:1 | 2 | #[macro_use] | ^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default error: useless lint attribute --> src/main.rs:1:1 | 1 | #[warn(clippy::macro_use_imports)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![warn(clippy::macro_use_imports)]` | = note: `#[deny(clippy::useless_attribute)]` on by default = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute
If I add the
!
as suggested then the error goes away, unsurprisingly.
So, IIUC, the behaviour does not change. Great! Let's go ahead with this PR.
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.
Excellent! Do you want me to do anything else, or is it ready for an r+?
@bors r+ |
📌 Commit be45f10 has been approved by |
☀️ Test successful - checks-actions |
Finished benchmarking commit (cdcc53b): comparison url. Instruction count
Max RSS (memory usage)Results
CyclesResults
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression Footnotes |
Best reviewed one commit at a time.
r? @cjgillot