From c8b4873cf90c542efbda7a27a8ad6ebdb099275e Mon Sep 17 00:00:00 2001 From: xFrednet Date: Thu, 16 Jun 2022 13:20:57 +0200 Subject: [PATCH] Add function to manually fulfill lint expectations (RFC 2383) --- compiler/rustc_lint/src/context.rs | 33 ++++++++++++++++++++++++++++- compiler/rustc_lint_defs/src/lib.rs | 7 ++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index eeb66f2d73871..cf5af7d481242 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -33,7 +33,7 @@ use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt}; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::Session; use rustc_span::lev_distance::find_best_match_for_name; @@ -887,6 +887,29 @@ pub trait LintContext: Sized { ) { self.lookup(lint, None as Option, decorate); } + + /// This returns the lint level for the given lint at the current location. + fn get_lint_level(&self, lint: &'static Lint) -> Level; + + /// This function can be used to manually fulfill an expectation. This can + /// be used for lints which contain several spans, and should be suppressed, + /// if either location was marked with an expectation. + /// + /// Note that this function should only be called for [`LintExpectationId`]s + /// retrieved from the current lint pass. Buffered or manually created ids can + /// cause ICEs. + fn fulfill_expectation(&self, expectation: LintExpectationId) { + // We need to make sure that submitted expectation ids are correctly fulfilled suppressed + // and stored between compilation sessions. To not manually do these steps, we simply create + // a dummy diagnostic and emit is as usual, which will be suppressed and stored like a normal + // expected lint diagnostic. + self.sess() + .struct_expect( + "this is a dummy diagnostic, to submit and store an expectation", + expectation, + ) + .emit(); + } } impl<'a> EarlyContext<'a> { @@ -934,6 +957,10 @@ impl LintContext for LateContext<'_> { None => self.tcx.struct_lint_node(lint, hir_id, decorate), } } + + fn get_lint_level(&self, lint: &'static Lint) -> Level { + self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).0 + } } impl LintContext for EarlyContext<'_> { @@ -956,6 +983,10 @@ impl LintContext for EarlyContext<'_> { ) { self.builder.struct_lint(lint, span.map(|s| s.into()), decorate) } + + fn get_lint_level(&self, lint: &'static Lint) -> Level { + self.builder.lint_level(lint).0 + } } impl<'tcx> LateContext<'tcx> { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index cb1c6f4098767..a35d830f711a5 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -229,6 +229,13 @@ impl Level { Level::Deny | Level::Forbid => true, } } + + pub fn get_expectation_id(&self) -> Option { + match self { + Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id), + _ => None, + } + } } /// Specification of a single lint.