1use std::any::Any;
2use std::borrow::Cow;
3
4use rustc_data_structures::sync::DynSend;
5use rustc_errors::{Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level};
6use rustc_hir::lints::{AttributeLintKind, FormatWarning};
7use rustc_middle::ty::TyCtxt;
8use rustc_session::Session;
9
10use crate::lints;
11
12mod check_cfg;
13
14pub struct DiagAndSess<'sess> {
15 pub callback: Box<
16 dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b, ()> + DynSend + 'static,
17 >,
18 pub sess: &'sess Session,
19}
20
21impl<'a> Diagnostic<'a, ()> for DiagAndSess<'_> {
22 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
23 (self.callback)(dcx, level, self.sess)
24 }
25}
26
27pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
30 pub sess: &'sess Session,
31 pub tcx: Option<TyCtxt<'tcx>>,
32 pub diagnostic: &'a AttributeLintKind,
33}
34
35impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
36 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
37 match self.diagnostic {
38 &AttributeLintKind::UnusedDuplicate { this, other, warning } => {
39 lints::UnusedDuplicate { this, other, warning }.into_diag(dcx, level)
40 }
41 AttributeLintKind::IllFormedAttributeInput { suggestions, docs, help } => {
42 lints::IllFormedAttributeInput {
43 num_suggestions: suggestions.len(),
44 suggestions: DiagArgValue::StrListSepByAnd(
45 suggestions.into_iter().map(|s| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", s))
})format!("`{s}`").into()).collect(),
46 ),
47 has_docs: docs.is_some(),
48 docs: docs.unwrap_or(""),
49 help: help.clone().map(|h| lints::IllFormedAttributeInputHelp { lint: h }),
50 }
51 .into_diag(dcx, level)
52 }
53 AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
54 lints::EmptyAttributeList {
55 attr_span: *first_span,
56 attr_path: attr_path.clone(),
57 valid_without_list: *valid_without_list,
58 }
59 .into_diag(dcx, level)
60 }
61 AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => {
62 lints::InvalidTargetLint {
63 name: name.clone(),
64 target,
65 applied: DiagArgValue::StrListSepByAnd(
66 applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
67 ),
68 only,
69 attr_span: *attr_span,
70 }
71 .into_diag(dcx, level)
72 }
73 &AttributeLintKind::InvalidStyle {
74 ref name,
75 is_used_as_inner,
76 target,
77 target_span,
78 } => lints::InvalidAttrStyle {
79 name: name.clone(),
80 is_used_as_inner,
81 target_span: (!is_used_as_inner).then_some(target_span),
82 target,
83 }
84 .into_diag(dcx, level),
85 &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => {
86 lints::UnsafeAttrOutsideUnsafeLint {
87 span: attribute_name_span,
88 suggestion: sugg_spans.map(|(left, right)| {
89 lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }
90 }),
91 }
92 .into_diag(dcx, level)
93 }
94 &AttributeLintKind::UnexpectedCfgName(name, value) => {
95 check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
96 .into_diag(dcx, level)
97 }
98 &AttributeLintKind::UnexpectedCfgValue(name, value) => {
99 check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
100 .into_diag(dcx, level)
101 }
102 &AttributeLintKind::DuplicateDocAlias { first_definition } => {
103 lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level)
104 }
105
106 &AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
107 lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level)
108 }
109
110 &AttributeLintKind::AmbiguousDeriveHelpers => {
111 lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
112 }
113
114 &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
115 lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.into_diag(dcx, level)
116 }
117
118 &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => {
119 lints::DocAutoCfgHideShowExpectsList { attr_name }.into_diag(dcx, level)
120 }
121
122 &AttributeLintKind::DocInvalid => lints::DocInvalid.into_diag(dcx, level),
123
124 &AttributeLintKind::DocUnknownInclude { span, inner, value } => {
125 lints::DocUnknownInclude {
126 inner,
127 value,
128 sugg: (span, Applicability::MaybeIncorrect),
129 }
130 .into_diag(dcx, level)
131 }
132
133 &AttributeLintKind::DocUnknownSpotlight { span } => {
134 lints::DocUnknownSpotlight { sugg_span: span }.into_diag(dcx, level)
135 }
136
137 &AttributeLintKind::DocUnknownPasses { name, span } => {
138 lints::DocUnknownPasses { name, note_span: span }.into_diag(dcx, level)
139 }
140
141 &AttributeLintKind::DocUnknownPlugins { span } => {
142 lints::DocUnknownPlugins { label_span: span }.into_diag(dcx, level)
143 }
144
145 &AttributeLintKind::DocUnknownAny { name } => {
146 lints::DocUnknownAny { name }.into_diag(dcx, level)
147 }
148
149 &AttributeLintKind::DocAutoCfgWrongLiteral => {
150 lints::DocAutoCfgWrongLiteral.into_diag(dcx, level)
151 }
152
153 &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level),
154
155 &AttributeLintKind::DocTestUnknown { name } => {
156 lints::DocTestUnknown { name }.into_diag(dcx, level)
157 }
158
159 &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level),
160
161 &AttributeLintKind::AttrCrateLevelOnly => {
162 lints::AttrCrateLevelOnly.into_diag(dcx, level)
163 }
164
165 &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
166 lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level)
167 }
168
169 &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
170 sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
171 }
172 .into_diag(dcx, level),
173
174 &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
175
176 &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
177
178 &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
179 &AttributeLintKind::MalformedOnUnimplementedAttr { span } => {
180 lints::MalformedOnUnimplementedAttrLint { span }.into_diag(dcx, level)
181 }
182 &AttributeLintKind::MalformedOnUnknownAttr { span } => {
183 lints::MalformedOnUnknownAttrLint { span }.into_diag(dcx, level)
184 }
185 &AttributeLintKind::MalformedOnConstAttr { span } => {
186 lints::MalformedOnConstAttrLint { span }.into_diag(dcx, level)
187 }
188 AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
189 FormatWarning::PositionalArgument { .. } => {
190 lints::DisallowedPositionalArgument.into_diag(dcx, level)
191 }
192 FormatWarning::InvalidSpecifier { .. } => {
193 lints::InvalidFormatSpecifier.into_diag(dcx, level)
194 }
195 FormatWarning::DisallowedPlaceholder { .. } => {
196 lints::DisallowedPlaceholder.into_diag(dcx, level)
197 }
198 },
199 AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
200 lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
201 }
202 &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
203 lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
204 .into_diag(dcx, level)
205 }
206 &AttributeLintKind::MissingOptionsForOnUnimplemented => {
207 lints::MissingOptionsForOnUnimplementedAttr.into_diag(dcx, level)
208 }
209 &AttributeLintKind::MissingOptionsForOnConst => {
210 lints::MissingOptionsForOnConstAttr.into_diag(dcx, level)
211 }
212 &AttributeLintKind::MalformedOnMoveAttr { span } => {
213 lints::MalformedOnMoveAttrLint { span }.into_diag(dcx, level)
214 }
215 &AttributeLintKind::OnMoveMalformedFormatLiterals { name } => {
216 lints::OnMoveMalformedFormatLiterals { name }.into_diag(dcx, level)
217 }
218 &AttributeLintKind::OnMoveMalformedAttrExpectedLiteralOrDelimiter => {
219 lints::OnMoveMalformedAttrExpectedLiteralOrDelimiter.into_diag(dcx, level)
220 }
221 &AttributeLintKind::MissingOptionsForOnMove => {
222 lints::MissingOptionsForOnMoveAttr.into_diag(dcx, level)
223 }
224 &AttributeLintKind::MissingOptionsForOnUnknown => {
225 lints::MissingOptionsForOnUnknownAttr.into_diag(dcx, level)
226 }
227 }
228 }
229}