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::{Lint, LintId};
9
10use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
11
12pub struct DecorateDiagCompat(
13 pub Box<
16 dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()>
17 + DynSync
18 + DynSend
19 + 'static,
20 >,
21);
22
23impl std::fmt::Debug for DecorateDiagCompat {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 f.debug_struct("DecorateDiagCompat").finish()
26 }
27}
28
29impl<D: for<'a> Diagnostic<'a, ()> + DynSync + DynSend + 'static> From<D> for DecorateDiagCompat {
30 #[inline]
31 fn from(d: D) -> Self {
32 Self(Box::new(|dcx, level, _| d.into_diag(dcx, level)))
33 }
34}
35
36#[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)]
39pub struct BufferedEarlyLint {
40 pub span: Option<MultiSpan>,
42
43 pub node_id: NodeId,
45
46 pub lint_id: LintId,
49
50 pub diagnostic: DecorateDiagCompat,
52}
53
54#[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)]
55pub struct LintBuffer {
56 pub map: FxIndexMap<NodeId, Vec<BufferedEarlyLint>>,
57}
58
59impl LintBuffer {
60 pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
61 self.map.entry(early_lint.node_id).or_default().push(early_lint);
62 }
63
64 pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
65 self.map.swap_remove(&id).unwrap_or_default()
67 }
68
69 pub fn buffer_lint(
70 &mut self,
71 lint: &'static Lint,
72 node_id: NodeId,
73 span: impl Into<MultiSpan>,
74 decorate: impl Into<DecorateDiagCompat>,
75 ) {
76 self.add_early_lint(BufferedEarlyLint {
77 lint_id: LintId::of(lint),
78 node_id,
79 span: Some(span.into()),
80 diagnostic: decorate.into(),
81 });
82 }
83
84 pub fn dyn_buffer_lint<
85 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
86 >(
87 &mut self,
88 lint: &'static Lint,
89 node_id: NodeId,
90 span: impl Into<MultiSpan>,
91 callback: F,
92 ) {
93 self.add_early_lint(BufferedEarlyLint {
94 lint_id: LintId::of(lint),
95 node_id,
96 span: Some(span.into()),
97 diagnostic: DecorateDiagCompat(Box::new(|dcx, level, _| callback(dcx, level))),
98 });
99 }
100
101 pub fn dyn_buffer_lint_any<
102 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()>
103 + DynSend
104 + DynSync
105 + 'static,
106 >(
107 &mut self,
108 lint: &'static Lint,
109 node_id: NodeId,
110 span: impl Into<MultiSpan>,
111 callback: F,
112 ) {
113 self.add_early_lint(BufferedEarlyLint {
114 lint_id: LintId::of(lint),
115 node_id,
116 span: Some(span.into()),
117 diagnostic: DecorateDiagCompat(Box::new(callback)),
118 });
119 }
120}