errors: introduce DecorateLint

Add a new trait to be generated by diagnostic derives which uses a
`LintDiagnosticBuilder`.

Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
David Wood 2022-06-29 16:07:46 +01:00
parent 2874f09534
commit 540eaf985d
6 changed files with 58 additions and 6 deletions

View File

@ -1,7 +1,7 @@
use crate::snippet::Style; use crate::snippet::Style;
use crate::{ use crate::{
CodeSuggestion, DiagnosticMessage, Level, MultiSpan, SubdiagnosticMessage, Substitution, CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan,
SubstitutionPart, SuggestionStyle, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
}; };
use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::stable_map::FxHashMap;
use rustc_error_messages::FluentValue; use rustc_error_messages::FluentValue;
@ -168,6 +168,14 @@ pub trait AddSubdiagnostic {
fn add_to_diagnostic(self, diag: &mut Diagnostic); fn add_to_diagnostic(self, diag: &mut Diagnostic);
} }
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
#[rustc_diagnostic_item = "DecorateLint"]
pub trait DecorateLint<'a, G: EmissionGuarantee> {
/// Decorate and emit a lint.
fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>);
}
#[must_use] #[must_use]
#[derive(Clone, Debug, Encodable, Decodable)] #[derive(Clone, Debug, Encodable, Decodable)]
pub struct Diagnostic { pub struct Diagnostic {

View File

@ -370,7 +370,7 @@ impl fmt::Display for ExplicitBug {
impl error::Error for ExplicitBug {} impl error::Error for ExplicitBug {}
pub use diagnostic::{ pub use diagnostic::{
AddSubdiagnostic, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, AddSubdiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
}; };
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder}; pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder};

View File

@ -22,7 +22,9 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync; use rustc_data_structures::sync;
use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err}; use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan, SuggestionStyle}; use rustc_errors::{
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::def_id::{CrateNum, DefId};
@ -870,6 +872,17 @@ pub trait LintContext: Sized {
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
); );
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
/// typically generated by `#[derive(LintDiagnostic)]`).
fn emit_spanned_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: S,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag));
}
fn struct_span_lint<S: Into<MultiSpan>>( fn struct_span_lint<S: Into<MultiSpan>>(
&self, &self,
lint: &'static Lint, lint: &'static Lint,
@ -878,6 +891,13 @@ pub trait LintContext: Sized {
) { ) {
self.lookup(lint, Some(span), decorate); self.lookup(lint, Some(span), decorate);
} }
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
/// generated by `#[derive(LintDiagnostic)]`).
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag));
}
/// Emit a lint at the appropriate level, with no associated span. /// Emit a lint at the appropriate level, with no associated span.
fn lint( fn lint(
&self, &self,

View File

@ -414,7 +414,7 @@ impl LateLintPass<'_> for Diagnostics {
let Impl { of_trait: Some(of_trait), .. } = impl_ && let Impl { of_trait: Some(of_trait), .. } = impl_ &&
let Some(def_id) = of_trait.trait_def_id() && let Some(def_id) = of_trait.trait_def_id() &&
let Some(name) = cx.tcx.get_diagnostic_name(def_id) && let Some(name) = cx.tcx.get_diagnostic_name(def_id) &&
matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic) matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic | sym::DecorateLint)
{ {
found_impl = true; found_impl = true;
break; break;

View File

@ -34,7 +34,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
use rustc_data_structures::vec_map::VecMap; use rustc_data_structures::vec_map::VecMap;
use rustc_errors::{ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan}; use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
@ -2787,6 +2787,18 @@ impl<'tcx> TyCtxt<'tcx> {
} }
} }
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
/// typically generated by `#[derive(LintDiagnostic)]`).
pub fn emit_spanned_lint(
self,
lint: &'static Lint,
hir_id: HirId,
span: impl Into<MultiSpan>,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
self.struct_span_lint_hir(lint, hir_id, span, |diag| decorator.decorate_lint(diag))
}
pub fn struct_span_lint_hir( pub fn struct_span_lint_hir(
self, self,
lint: &'static Lint, lint: &'static Lint,
@ -2798,6 +2810,17 @@ impl<'tcx> TyCtxt<'tcx> {
struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate); struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
} }
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
/// generated by `#[derive(LintDiagnostic)]`).
pub fn emit_lint(
self,
lint: &'static Lint,
id: HirId,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
self.struct_lint_node(lint, id, |diag| decorator.decorate_lint(diag))
}
pub fn struct_lint_node( pub fn struct_lint_node(
self, self,
lint: &'static Lint, lint: &'static Lint,

View File

@ -173,6 +173,7 @@ symbols! {
DebugTuple, DebugTuple,
Decodable, Decodable,
Decoder, Decoder,
DecorateLint,
Default, Default,
Deref, Deref,
DiagnosticMessage, DiagnosticMessage,