rustc_errors/
decorate_diag.rs1use std::any::Any;
2
3use rustc_ast::node_id::NodeId;
5use rustc_data_structures::fx::FxIndexMap;
6use rustc_data_structures::sync::{DynSend, DynSync};
7use rustc_error_messages::MultiSpan;
8use rustc_lint_defs::{AttributeLintKind, Lint, LintId};
9
10use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
11
12pub enum DecorateDiagCompat {
15 Dynamic(
18 Box<
19 dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()>
20 + DynSync
21 + DynSend
22 + 'static,
23 >,
24 ),
25 Builtin(AttributeLintKind),
26}
27
28impl std::fmt::Debug for DecorateDiagCompat {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 f.debug_struct("DecorateDiagCompat").finish()
31 }
32}
33
34impl<D: for<'a> Diagnostic<'a, ()> + DynSync + DynSend + 'static> From<D> for DecorateDiagCompat {
35 #[inline]
36 fn from(d: D) -> Self {
37 Self::Dynamic(Box::new(|dcx, level, _| d.into_diag(dcx, level)))
38 }
39}
40
41impl From<AttributeLintKind> for DecorateDiagCompat {
42 #[inline]
43 fn from(b: AttributeLintKind) -> Self {
44 Self::Builtin(b)
45 }
46}
47
48#[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)]
51pub struct BufferedEarlyLint {
52 pub span: Option<MultiSpan>,
54
55 pub node_id: NodeId,
57
58 pub lint_id: LintId,
61
62 pub diagnostic: DecorateDiagCompat,
64}
65
66#[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)]
67pub struct LintBuffer {
68 pub map: FxIndexMap<NodeId, Vec<BufferedEarlyLint>>,
69}
70
71impl LintBuffer {
72 pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
73 self.map.entry(early_lint.node_id).or_default().push(early_lint);
74 }
75
76 pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
77 self.map.swap_remove(&id).unwrap_or_default()
79 }
80
81 pub fn buffer_lint(
82 &mut self,
83 lint: &'static Lint,
84 node_id: NodeId,
85 span: impl Into<MultiSpan>,
86 decorate: impl Into<DecorateDiagCompat>,
87 ) {
88 self.add_early_lint(BufferedEarlyLint {
89 lint_id: LintId::of(lint),
90 node_id,
91 span: Some(span.into()),
92 diagnostic: decorate.into(),
93 });
94 }
95
96 pub fn dyn_buffer_lint<
97 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
98 >(
99 &mut self,
100 lint: &'static Lint,
101 node_id: NodeId,
102 span: impl Into<MultiSpan>,
103 callback: F,
104 ) {
105 self.add_early_lint(BufferedEarlyLint {
106 lint_id: LintId::of(lint),
107 node_id,
108 span: Some(span.into()),
109 diagnostic: DecorateDiagCompat::Dynamic(Box::new(|dcx, level, _| callback(dcx, level))),
110 });
111 }
112
113 pub fn dyn_buffer_lint_any<
114 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()>
115 + DynSend
116 + DynSync
117 + 'static,
118 >(
119 &mut self,
120 lint: &'static Lint,
121 node_id: NodeId,
122 span: impl Into<MultiSpan>,
123 callback: F,
124 ) {
125 self.add_early_lint(BufferedEarlyLint {
126 lint_id: LintId::of(lint),
127 node_id,
128 span: Some(span.into()),
129 diagnostic: DecorateDiagCompat::Dynamic(Box::new(callback)),
130 });
131 }
132}