1use std::borrow::Cow;
2
3use rustc_errors::{
4 Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level,
5 elided_lifetime_in_path_suggestion,
6};
7use rustc_hir::lints::{AttributeLintKind, FormatWarning};
8use rustc_middle::ty::TyCtxt;
9use rustc_session::Session;
10use rustc_session::lint::BuiltinLintDiag;
11use tracing::debug;
12
13use crate::lints;
14
15mod check_cfg;
16
17pub struct DecorateBuiltinLint<'sess, 'tcx> {
20 pub sess: &'sess Session,
21 pub tcx: Option<TyCtxt<'tcx>>,
22 pub diagnostic: BuiltinLintDiag,
23}
24
25impl<'a> Diagnostic<'a, ()> for DecorateBuiltinLint<'_, '_> {
26 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
27 match self.diagnostic {
28 BuiltinLintDiag::AbsPathWithModule(mod_span) => {
29 let (replacement, applicability) =
30 match self.sess.source_map().span_to_snippet(mod_span) {
31 Ok(ref s) => {
32 let opt_colon =
35 if s.trim_start().starts_with("::") { "" } else { "::" };
36
37 (::alloc::__export::must_use({
::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
})format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
38 }
39 Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
40 };
41 lints::AbsPathWithModule {
42 sugg: lints::AbsPathWithModuleSugg {
43 span: mod_span,
44 applicability,
45 replacement,
46 },
47 }
48 .into_diag(dcx, level)
49 }
50 BuiltinLintDiag::ElidedLifetimesInPaths(
51 n,
52 path_span,
53 incl_angl_brckt,
54 insertion_span,
55 ) => lints::ElidedLifetimesInPaths {
56 subdiag: elided_lifetime_in_path_suggestion(
57 self.sess.source_map(),
58 n,
59 path_span,
60 incl_angl_brckt,
61 insertion_span,
62 ),
63 }
64 .into_diag(dcx, level),
65 BuiltinLintDiag::UnusedImports {
66 remove_whole_use,
67 num_to_remove,
68 remove_spans,
69 test_module_span,
70 span_snippets,
71 } => {
72 let sugg = if remove_whole_use {
73 lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] }
74 } else {
75 lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove }
76 };
77 let test_module_span =
78 test_module_span.map(|span| self.sess.source_map().guess_head_span(span));
79
80 lints::UnusedImports {
81 sugg,
82 test_module_span,
83 num_snippets: span_snippets.len(),
84 span_snippets: DiagArgValue::StrListSepByAnd(
85 span_snippets.into_iter().map(Cow::Owned).collect(),
86 ),
87 }
88 .into_diag(dcx, level)
89 }
90 BuiltinLintDiag::SingleUseLifetime {
91 param_span,
92 use_span,
93 elidable,
94 deletion_span,
95 ident,
96 } => {
97 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/early/diagnostics.rs:97",
"rustc_lint::early::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/early/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(97u32),
::tracing_core::__macro_support::Option::Some("rustc_lint::early::diagnostics"),
::tracing_core::field::FieldSet::new(&["param_span",
"use_span", "deletion_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(¶m_span)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&use_span)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&deletion_span)
as &dyn Value))])
});
} else { ; }
};debug!(?param_span, ?use_span, ?deletion_span);
98 let suggestion = if let Some(deletion_span) = deletion_span {
99 let (use_span, replace_lt) = if elidable {
100 let use_span =
101 self.sess.source_map().span_extend_while_whitespace(use_span);
102 (use_span, String::new())
103 } else {
104 (use_span, "'_".to_owned())
105 };
106 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/early/diagnostics.rs:106",
"rustc_lint::early::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/early/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(106u32),
::tracing_core::__macro_support::Option::Some("rustc_lint::early::diagnostics"),
::tracing_core::field::FieldSet::new(&["deletion_span",
"use_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&deletion_span)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&use_span)
as &dyn Value))])
});
} else { ; }
};debug!(?deletion_span, ?use_span);
107
108 let deletion_span =
111 if deletion_span.is_empty() { None } else { Some(deletion_span) };
112 Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt })
113 } else {
114 None
115 };
116
117 lints::SingleUseLifetime { suggestion, param_span, use_span, ident }
118 .into_diag(dcx, level)
119 }
120 BuiltinLintDiag::NamedArgumentUsedPositionally {
121 position_sp_to_replace,
122 position_sp_for_msg,
123 named_arg_sp,
124 named_arg_name,
125 is_formatting_arg,
126 } => {
127 let (suggestion, name) =
128 if let Some(positional_arg_to_replace) = position_sp_to_replace {
129 let mut name = named_arg_name.clone();
130 if is_formatting_arg {
131 name.push('$')
132 };
133 let span_to_replace = if let Ok(positional_arg_content) =
134 self.sess.source_map().span_to_snippet(positional_arg_to_replace)
135 && positional_arg_content.starts_with(':')
136 {
137 positional_arg_to_replace.shrink_to_lo()
138 } else {
139 positional_arg_to_replace
140 };
141 (Some(span_to_replace), name)
142 } else {
143 (None, String::new())
144 };
145
146 lints::NamedArgumentUsedPositionally {
147 named_arg_sp,
148 position_label_sp: position_sp_for_msg,
149 suggestion,
150 name,
151 named_arg_name,
152 }
153 .into_diag(dcx, level)
154 }
155
156 BuiltinLintDiag::AttributeLint(kind) => {
157 DecorateAttrLint { sess: self.sess, tcx: self.tcx, diagnostic: &kind }
158 .into_diag(dcx, level)
159 }
160 }
161 }
162}
163
164pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
167 pub sess: &'sess Session,
168 pub tcx: Option<TyCtxt<'tcx>>,
169 pub diagnostic: &'a AttributeLintKind,
170}
171
172impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
173 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
174 match self.diagnostic {
175 &AttributeLintKind::UnusedDuplicate { this, other, warning } => {
176 lints::UnusedDuplicate { this, other, warning }.into_diag(dcx, level)
177 }
178 AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => {
179 lints::IllFormedAttributeInput {
180 num_suggestions: suggestions.len(),
181 suggestions: DiagArgValue::StrListSepByAnd(
182 suggestions.into_iter().map(|s| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", s))
})format!("`{s}`").into()).collect(),
183 ),
184 has_docs: docs.is_some(),
185 docs: docs.unwrap_or(""),
186 }
187 .into_diag(dcx, level)
188 }
189 AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
190 lints::EmptyAttributeList {
191 attr_span: *first_span,
192 attr_path: attr_path.clone(),
193 valid_without_list: *valid_without_list,
194 }
195 .into_diag(dcx, level)
196 }
197 AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => {
198 lints::InvalidTargetLint {
199 name: name.clone(),
200 target,
201 applied: DiagArgValue::StrListSepByAnd(
202 applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
203 ),
204 only,
205 attr_span: *attr_span,
206 }
207 .into_diag(dcx, level)
208 }
209 &AttributeLintKind::InvalidStyle {
210 ref name,
211 is_used_as_inner,
212 target,
213 target_span,
214 } => lints::InvalidAttrStyle {
215 name: name.clone(),
216 is_used_as_inner,
217 target_span: (!is_used_as_inner).then_some(target_span),
218 target,
219 }
220 .into_diag(dcx, level),
221 &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => {
222 lints::UnsafeAttrOutsideUnsafeLint {
223 span: attribute_name_span,
224 suggestion: sugg_spans.map(|(left, right)| {
225 lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }
226 }),
227 }
228 .into_diag(dcx, level)
229 }
230 &AttributeLintKind::UnexpectedCfgName(name, value) => {
231 check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
232 .into_diag(dcx, level)
233 }
234 &AttributeLintKind::UnexpectedCfgValue(name, value) => {
235 check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
236 .into_diag(dcx, level)
237 }
238 &AttributeLintKind::DuplicateDocAlias { first_definition } => {
239 lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level)
240 }
241
242 &AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
243 lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level)
244 }
245
246 &AttributeLintKind::AmbiguousDeriveHelpers => {
247 lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
248 }
249
250 &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
251 lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.into_diag(dcx, level)
252 }
253
254 &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => {
255 lints::DocAutoCfgHideShowExpectsList { attr_name }.into_diag(dcx, level)
256 }
257
258 &AttributeLintKind::DocInvalid => lints::DocInvalid.into_diag(dcx, level),
259
260 &AttributeLintKind::DocUnknownInclude { span, inner, value } => {
261 lints::DocUnknownInclude {
262 inner,
263 value,
264 sugg: (span, Applicability::MaybeIncorrect),
265 }
266 .into_diag(dcx, level)
267 }
268
269 &AttributeLintKind::DocUnknownSpotlight { span } => {
270 lints::DocUnknownSpotlight { sugg_span: span }.into_diag(dcx, level)
271 }
272
273 &AttributeLintKind::DocUnknownPasses { name, span } => {
274 lints::DocUnknownPasses { name, note_span: span }.into_diag(dcx, level)
275 }
276
277 &AttributeLintKind::DocUnknownPlugins { span } => {
278 lints::DocUnknownPlugins { label_span: span }.into_diag(dcx, level)
279 }
280
281 &AttributeLintKind::DocUnknownAny { name } => {
282 lints::DocUnknownAny { name }.into_diag(dcx, level)
283 }
284
285 &AttributeLintKind::DocAutoCfgWrongLiteral => {
286 lints::DocAutoCfgWrongLiteral.into_diag(dcx, level)
287 }
288
289 &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level),
290
291 &AttributeLintKind::DocTestUnknown { name } => {
292 lints::DocTestUnknown { name }.into_diag(dcx, level)
293 }
294
295 &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level),
296
297 &AttributeLintKind::AttrCrateLevelOnly => {
298 lints::AttrCrateLevelOnly.into_diag(dcx, level)
299 }
300
301 &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
302 lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level)
303 }
304
305 &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
306 sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
307 }
308 .into_diag(dcx, level),
309
310 &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
311
312 &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
313
314 &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
315 &AttributeLintKind::MalformedOnUnimplementedAttr { span } => {
316 lints::MalformedOnUnimplementedAttrLint { span }.into_diag(dcx, level)
317 }
318 &AttributeLintKind::MalformedOnConstAttr { span } => {
319 lints::MalformedOnConstAttrLint { span }.into_diag(dcx, level)
320 }
321 AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
322 FormatWarning::PositionalArgument { .. } => {
323 lints::DisallowedPositionalArgument.into_diag(dcx, level)
324 }
325 FormatWarning::InvalidSpecifier { .. } => {
326 lints::InvalidFormatSpecifier.into_diag(dcx, level)
327 }
328 },
329 AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
330 lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
331 }
332 &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
333 lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
334 .into_diag(dcx, level)
335 }
336 &AttributeLintKind::MissingOptionsForOnUnimplemented => {
337 lints::MissingOptionsForOnUnimplementedAttr.into_diag(dcx, level)
338 }
339 &AttributeLintKind::MissingOptionsForOnConst => {
340 lints::MissingOptionsForOnConstAttr.into_diag(dcx, level)
341 }
342 &AttributeLintKind::MalformedOnMoveAttr { span } => {
343 lints::MalformedOnMoveAttrLint { span }.into_diag(dcx, level)
344 }
345 &AttributeLintKind::OnMoveMalformedFormatLiterals { name } => {
346 lints::OnMoveMalformedFormatLiterals { name }.into_diag(dcx, level)
347 }
348 &AttributeLintKind::OnMoveMalformedAttrExpectedLiteralOrDelimiter => {
349 lints::OnMoveMalformedAttrExpectedLiteralOrDelimiter.into_diag(dcx, level)
350 }
351 &AttributeLintKind::MissingOptionsForOnMove => {
352 lints::MissingOptionsForOnMoveAttr.into_diag(dcx, level)
353 }
354 }
355 }
356}