diff options
| author | xFrednet <xFrednet@gmail.com> | 2022-03-29 00:10:45 +0200 |
|---|---|---|
| committer | xFrednet <xFrednet@gmail.com> | 2022-05-08 14:37:14 +0200 |
| commit | 2c5e85249f8b10b5fb0caf608d8b2537620285c6 (patch) | |
| tree | 8d3d6e7b8e79d54df8b5eda69dbe45923b666a47 /compiler | |
| parent | 7f03681cd941c7e18ee99549148b8aa6f468d7c2 (diff) | |
| download | rust-2c5e85249f8b10b5fb0caf608d8b2537620285c6.tar.gz rust-2c5e85249f8b10b5fb0caf608d8b2537620285c6.zip | |
Move lint expectation checking into a separate query (RFC 2383)
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/expect.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/late.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/levels.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/lint.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_query_impl/src/keys.rs | 10 |
8 files changed, 68 insertions, 13 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 08987dff660..00119267e85 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1009,6 +1009,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); } ); + + // This check has to be run after all lints are done processing. We don't + // define a lint filter, as all lint checks should have finished at this point. + sess.time("check_lint_expectations", || tcx.check_expectations(None)); }); Ok(()) diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 67f5aa0540f..dc48ac0a618 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,10 +1,16 @@ use crate::builtin; use rustc_hir::HirId; +use rustc_middle::ty::query::Providers; use rustc_middle::{lint::LintExpectation, ty::TyCtxt}; use rustc_session::lint::LintExpectationId; use rustc_span::symbol::sym; +use rustc_span::Symbol; -pub fn check_expectations(tcx: TyCtxt<'_>) { +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { check_expectations, ..*providers }; +} + +fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) { if !tcx.sess.features_untracked().enabled(sym::lint_reasons) { return; } @@ -13,7 +19,9 @@ pub fn check_expectations(tcx: TyCtxt<'_>) { let lint_expectations = &tcx.lint_levels(()).lint_expectations; for (id, expectation) in lint_expectations { - if !fulfilled_expectations.contains(id) { + if !fulfilled_expectations.contains(id) + && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) + { // This check will always be true, since `lint_expectations` only // holds stable ids if let LintExpectationId::Stable { hir_id, .. } = id { diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 0ac636b878e..0ce760b64d9 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -503,7 +503,4 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( }); }, ); - - // This check has to be run after all lints are done processing for this crate - tcx.sess.time("check_lint_expectations", || crate::expect::check_expectations(tcx)); } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 01f1d1e79ac..257549bf1a1 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -371,7 +371,12 @@ impl<'s> LintLevelsBuilder<'s> { }; self.lint_expectations.push(( expect_id, - LintExpectation::new(reason, sp, is_unfulfilled_lint_expectations), + LintExpectation::new( + reason, + sp, + is_unfulfilled_lint_expectations, + tool_name, + ), )); } let src = LintLevelSource::Node( @@ -400,8 +405,10 @@ impl<'s> LintLevelsBuilder<'s> { self.insert_spec(*id, (level, src)); } if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp, false))); + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + )); } } Err((Some(ids), ref new_lint_name)) => { @@ -444,8 +451,10 @@ impl<'s> LintLevelsBuilder<'s> { self.insert_spec(*id, (level, src)); } if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp, false))); + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + )); } } Err((None, _)) => { @@ -550,8 +559,10 @@ impl<'s> LintLevelsBuilder<'s> { } } if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp, false))); + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + )); } } else { panic!("renamed lint does not exist: {}", new_name); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 028c14366c6..a965587afb7 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -109,6 +109,7 @@ pub use rustc_session::lint::{LintArray, LintPass}; pub fn provide(providers: &mut Providers) { levels::provide(providers); + expect::provide(providers); *providers = Providers { lint_mod, ..*providers }; } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index e55b0454eef..c7c5f56867a 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -210,6 +210,10 @@ pub struct LintExpectation { /// adjusted to include an additional note. Therefore, we have to track if /// the expectation is for the lint. pub is_unfulfilled_lint_expectations: bool, + /// This will hold the name of the tool that this lint belongs to. For + /// the lint `clippy::some_lint` the tool would be `clippy`, the same + /// goes for `rustdoc`. This will be `None` for rustc lints + pub lint_tool: Option<Symbol>, } impl LintExpectation { @@ -217,8 +221,9 @@ impl LintExpectation { reason: Option<Symbol>, emission_span: Span, is_unfulfilled_lint_expectations: bool, + lint_tool: Option<Symbol>, ) -> Self { - Self { reason, emission_span, is_unfulfilled_lint_expectations } + Self { reason, emission_span, is_unfulfilled_lint_expectations, lint_tool } } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e439d128dbc..3936b3f0d68 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -157,6 +157,25 @@ rustc_queries! { desc { "running analysis passes on this crate" } } + /// This query checks the fulfillment of collected lint expectations. + /// All lint emitting queries have to be done before this is executed + /// to ensure that all expectations can be fulfilled. + /// + /// This is an extra query to enable other drivers (like rustdoc) to + /// only execute a small subset of the [`analysis`] query, while allowing + /// lints to be expected. In rustc, this query will be executed as part of + /// the [`analysis`] query and doesn't have to be called a second time. + /// + /// Tools can additionally pass in a tool filter. That will restrict the + /// expectations to only trigger for lints starting with the listed tool + /// name. This is useful for cases were not all linting code from rustc + /// was called. With the default `none` all registered lints will also + /// be checked for expectation fulfillment. + query check_expectations(key: Option<Symbol>) -> () { + eval_always + desc { "checking lint expectations (RFC 2383)" } + } + /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its /// associated generics. query generics_of(key: DefId) -> ty::Generics { diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 3f0f856b5dd..6fbafeb1d32 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -435,6 +435,16 @@ impl Key for Symbol { } } +impl Key for Option<Symbol> { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. impl<'tcx, T> Key for Canonical<'tcx, T> { |
