rustc_errors/
decorate_diag.rs1use rustc_ast::node_id::NodeId;
3use rustc_data_structures::fx::FxIndexMap;
4use rustc_data_structures::sync::{DynSend, DynSync};
5use rustc_error_messages::MultiSpan;
6use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId};
7
8use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
9
10pub enum DecorateDiagCompat {
13 Dynamic(
14 Box<
15 dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()>
16 + DynSync
17 + DynSend
18 + 'static,
19 >,
20 ),
21 Builtin(BuiltinLintDiag),
22}
23
24impl std::fmt::Debug for DecorateDiagCompat {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 f.debug_struct("DecorateDiagCompat").finish()
27 }
28}
29
30impl<D: for<'a> Diagnostic<'a, ()> + DynSync + DynSend + 'static> From<D> for DecorateDiagCompat {
31 #[inline]
32 fn from(d: D) -> Self {
33 Self::Dynamic(Box::new(|dcx, level| d.into_diag(dcx, level)))
34 }
35}
36
37impl From<BuiltinLintDiag> for DecorateDiagCompat {
38 #[inline]
39 fn from(b: BuiltinLintDiag) -> Self {
40 Self::Builtin(b)
41 }
42}
43
44#[derive(#[automatically_derived]
impl ::core::fmt::Debug for BufferedEarlyLint {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"BufferedEarlyLint", "span", &self.span, "node_id", &self.node_id,
"lint_id", &self.lint_id, "diagnostic", &&self.diagnostic)
}
}Debug)]
47pub struct BufferedEarlyLint {
48 pub span: Option<MultiSpan>,
50
51 pub node_id: NodeId,
53
54 pub lint_id: LintId,
57
58 pub diagnostic: DecorateDiagCompat,
60}
61
62#[derive(#[automatically_derived]
impl ::core::default::Default for LintBuffer {
#[inline]
fn default() -> LintBuffer {
LintBuffer { map: ::core::default::Default::default() }
}
}Default, #[automatically_derived]
impl ::core::fmt::Debug for LintBuffer {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "LintBuffer",
"map", &&self.map)
}
}Debug)]
63pub struct LintBuffer {
64 pub map: FxIndexMap<NodeId, Vec<BufferedEarlyLint>>,
65}
66
67impl LintBuffer {
68 pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
69 self.map.entry(early_lint.node_id).or_default().push(early_lint);
70 }
71
72 pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
73 self.map.swap_remove(&id).unwrap_or_default()
75 }
76
77 pub fn buffer_lint(
78 &mut self,
79 lint: &'static Lint,
80 node_id: NodeId,
81 span: impl Into<MultiSpan>,
82 decorate: impl Into<DecorateDiagCompat>,
83 ) {
84 self.add_early_lint(BufferedEarlyLint {
85 lint_id: LintId::of(lint),
86 node_id,
87 span: Some(span.into()),
88 diagnostic: decorate.into(),
89 });
90 }
91
92 pub fn dyn_buffer_lint<
93 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
94 >(
95 &mut self,
96 lint: &'static Lint,
97 node_id: NodeId,
98 span: impl Into<MultiSpan>,
99 callback: F,
100 ) {
101 self.add_early_lint(BufferedEarlyLint {
102 lint_id: LintId::of(lint),
103 node_id,
104 span: Some(span.into()),
105 diagnostic: DecorateDiagCompat::Dynamic(Box::new(callback)),
106 });
107 }
108}