Add function to manually fulfill lint expectations (RFC 2383)

This commit is contained in:
xFrednet 2022-06-16 13:20:57 +02:00
parent 6c6388cd6c
commit c8b4873cf9
No known key found for this signature in database
GPG Key ID: F5C59D0E669E5302
2 changed files with 39 additions and 1 deletions

View File

@ -33,7 +33,7 @@ use rustc_middle::middle::stability;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt}; 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::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::lev_distance::find_best_match_for_name;
@ -887,6 +887,29 @@ pub trait LintContext: Sized {
) { ) {
self.lookup(lint, None as Option<Span>, decorate); self.lookup(lint, None as Option<Span>, 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> { impl<'a> EarlyContext<'a> {
@ -934,6 +957,10 @@ impl LintContext for LateContext<'_> {
None => self.tcx.struct_lint_node(lint, hir_id, decorate), 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<'_> { impl LintContext for EarlyContext<'_> {
@ -956,6 +983,10 @@ impl LintContext for EarlyContext<'_> {
) { ) {
self.builder.struct_lint(lint, span.map(|s| s.into()), decorate) 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> { impl<'tcx> LateContext<'tcx> {

View File

@ -229,6 +229,13 @@ impl Level {
Level::Deny | Level::Forbid => true, Level::Deny | Level::Forbid => true,
} }
} }
pub fn get_expectation_id(&self) -> Option<LintExpectationId> {
match self {
Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id),
_ => None,
}
}
} }
/// Specification of a single lint. /// Specification of a single lint.