Skip to main content

rustc_lint/early/
diagnostics.rs

1use std::borrow::Cow;
2
3use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
4use rustc_errors::{
5    Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level,
6    elided_lifetime_in_path_suggestion,
7};
8use rustc_hir::lints::{AttributeLintKind, FormatWarning};
9use rustc_middle::middle::stability;
10use rustc_middle::ty::TyCtxt;
11use rustc_session::Session;
12use rustc_session::lint::BuiltinLintDiag;
13use rustc_span::BytePos;
14use tracing::debug;
15
16use crate::lints;
17
18mod check_cfg;
19
20/// This is a diagnostic struct that will decorate a `BuiltinLintDiag`
21/// Directly creating the lint structs is expensive, using this will only decorate the lint structs when needed.
22pub struct DecorateBuiltinLint<'sess, 'tcx> {
23    pub sess: &'sess Session,
24    pub tcx: Option<TyCtxt<'tcx>>,
25    pub diagnostic: BuiltinLintDiag,
26}
27
28impl<'a> Diagnostic<'a, ()> for DecorateBuiltinLint<'_, '_> {
29    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
30        match self.diagnostic {
31            BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => {
32                let spans: Vec<_> = content
33                    .char_indices()
34                    .filter_map(|(i, c)| {
35                        TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
36                            let lo = comment_span.lo() + BytePos(2 + i as u32);
37                            (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
38                        })
39                    })
40                    .collect();
41                let characters = spans
42                    .iter()
43                    .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", c))
    })format!("{c:?}") })
44                    .collect();
45                let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion {
46                    spans: spans.iter().map(|(_c, span)| *span).collect(),
47                });
48
49                lints::UnicodeTextFlow {
50                    comment_span,
51                    characters,
52                    suggestions,
53                    num_codepoints: spans.len(),
54                }
55                .into_diag(dcx, level)
56            }
57            BuiltinLintDiag::AbsPathWithModule(mod_span) => {
58                let (replacement, applicability) =
59                    match self.sess.source_map().span_to_snippet(mod_span) {
60                        Ok(ref s) => {
61                            // FIXME(Manishearth) ideally the emitting code
62                            // can tell us whether or not this is global
63                            let opt_colon =
64                                if s.trim_start().starts_with("::") { "" } else { "::" };
65
66                            (::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
    })format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
67                        }
68                        Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
69                    };
70                lints::AbsPathWithModule {
71                    sugg: lints::AbsPathWithModuleSugg {
72                        span: mod_span,
73                        applicability,
74                        replacement,
75                    },
76                }
77                .into_diag(dcx, level)
78            }
79            BuiltinLintDiag::ElidedLifetimesInPaths(
80                n,
81                path_span,
82                incl_angl_brckt,
83                insertion_span,
84            ) => lints::ElidedLifetimesInPaths {
85                subdiag: elided_lifetime_in_path_suggestion(
86                    self.sess.source_map(),
87                    n,
88                    path_span,
89                    incl_angl_brckt,
90                    insertion_span,
91                ),
92            }
93            .into_diag(dcx, level),
94            BuiltinLintDiag::UnusedImports {
95                remove_whole_use,
96                num_to_remove,
97                remove_spans,
98                test_module_span,
99                span_snippets,
100            } => {
101                let sugg = if remove_whole_use {
102                    lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] }
103                } else {
104                    lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove }
105                };
106                let test_module_span =
107                    test_module_span.map(|span| self.sess.source_map().guess_head_span(span));
108
109                lints::UnusedImports {
110                    sugg,
111                    test_module_span,
112                    num_snippets: span_snippets.len(),
113                    span_snippets: DiagArgValue::StrListSepByAnd(
114                        span_snippets.into_iter().map(Cow::Owned).collect(),
115                    ),
116                }
117                .into_diag(dcx, level)
118            }
119            BuiltinLintDiag::RedundantImport(spans, ident) => {
120                let subs = spans
121                    .into_iter()
122                    .map(|(span, is_imported)| match (span.is_dummy(), is_imported) {
123                        (false, true) => lints::RedundantImportSub::ImportedHere { span, ident },
124                        (false, false) => lints::RedundantImportSub::DefinedHere { span, ident },
125                        (true, true) => lints::RedundantImportSub::ImportedPrelude { span, ident },
126                        (true, false) => lints::RedundantImportSub::DefinedPrelude { span, ident },
127                    })
128                    .collect();
129                lints::RedundantImport { subs, ident }.into_diag(dcx, level)
130            }
131            BuiltinLintDiag::DeprecatedMacro {
132                suggestion,
133                suggestion_span,
134                note,
135                path,
136                since_kind,
137            } => {
138                let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion {
139                    span: suggestion_span,
140                    kind: "macro".to_owned(),
141                    suggestion,
142                });
143
144                stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
145                    .into_diag(dcx, level)
146            }
147            BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
148                let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
149                if is_foreign {
150                    lints::PatternsInFnsWithoutBody::Foreign { sub }
151                } else {
152                    lints::PatternsInFnsWithoutBody::Bodiless { sub }
153                }
154                .into_diag(dcx, level)
155            }
156            BuiltinLintDiag::ReservedPrefix(label_span, prefix) => lints::ReservedPrefix {
157                label: label_span,
158                suggestion: label_span.shrink_to_hi(),
159                prefix,
160            }
161            .into_diag(dcx, level),
162            BuiltinLintDiag::RawPrefix(label_span) => {
163                lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }
164                    .into_diag(dcx, level)
165            }
166            BuiltinLintDiag::ReservedString { is_string, suggestion } => {
167                if is_string {
168                    lints::ReservedString { suggestion }.into_diag(dcx, level)
169                } else {
170                    lints::ReservedMultihash { suggestion }.into_diag(dcx, level)
171                }
172            }
173            BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => lints::BreakWithLabelAndLoop {
174                sub: lints::BreakWithLabelAndLoopSub {
175                    left: sugg_span.shrink_to_lo(),
176                    right: sugg_span.shrink_to_hi(),
177                },
178            }
179            .into_diag(dcx, level),
180            BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
181                let suggestion = match sugg {
182                    Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd {
183                        left: left_sp,
184                        right: right_sp,
185                        sugg,
186                    },
187                    None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp },
188                };
189                lints::DeprecatedWhereClauseLocation { suggestion }.into_diag(dcx, level)
190            }
191            BuiltinLintDiag::SingleUseLifetime {
192                param_span,
193                use_span: Some((use_span, elide)),
194                deletion_span,
195                ident,
196            } => {
197                {
    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:197",
                        "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(197u32),
                        ::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(&param_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);
198                let suggestion = if let Some(deletion_span) = deletion_span {
199                    let (use_span, replace_lt) = if elide {
200                        let use_span =
201                            self.sess.source_map().span_extend_while_whitespace(use_span);
202                        (use_span, String::new())
203                    } else {
204                        (use_span, "'_".to_owned())
205                    };
206                    {
    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:206",
                        "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(206u32),
                        ::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);
207
208                    // issue 107998 for the case such as a wrong function pointer type
209                    // `deletion_span` is empty and there is no need to report lifetime uses here
210                    let deletion_span =
211                        if deletion_span.is_empty() { None } else { Some(deletion_span) };
212                    Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt })
213                } else {
214                    None
215                };
216
217                lints::SingleUseLifetime { suggestion, param_span, use_span, ident }
218                    .into_diag(dcx, level)
219            }
220            BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
221                lints::UnusedLifetime { deletion_span, ident }.into_diag(dcx, level)
222            }
223            BuiltinLintDiag::NamedArgumentUsedPositionally {
224                position_sp_to_replace,
225                position_sp_for_msg,
226                named_arg_sp,
227                named_arg_name,
228                is_formatting_arg,
229            } => {
230                let (suggestion, name) =
231                    if let Some(positional_arg_to_replace) = position_sp_to_replace {
232                        let mut name = named_arg_name.clone();
233                        if is_formatting_arg {
234                            name.push('$')
235                        };
236                        let span_to_replace = if let Ok(positional_arg_content) =
237                            self.sess.source_map().span_to_snippet(positional_arg_to_replace)
238                            && positional_arg_content.starts_with(':')
239                        {
240                            positional_arg_to_replace.shrink_to_lo()
241                        } else {
242                            positional_arg_to_replace
243                        };
244                        (Some(span_to_replace), name)
245                    } else {
246                        (None, String::new())
247                    };
248
249                lints::NamedArgumentUsedPositionally {
250                    named_arg_sp,
251                    position_label_sp: position_sp_for_msg,
252                    suggestion,
253                    name,
254                    named_arg_name,
255                }
256                .into_diag(dcx, level)
257            }
258            BuiltinLintDiag::AmbiguousGlobReexports {
259                name,
260                namespace,
261                first_reexport_span,
262                duplicate_reexport_span,
263            } => lints::AmbiguousGlobReexports {
264                first_reexport: first_reexport_span,
265                duplicate_reexport: duplicate_reexport_span,
266                name,
267                namespace,
268            }
269            .into_diag(dcx, level),
270            BuiltinLintDiag::HiddenGlobReexports {
271                name,
272                namespace,
273                glob_reexport_span,
274                private_item_span,
275            } => lints::HiddenGlobReexports {
276                glob_reexport: glob_reexport_span,
277                private_item: private_item_span,
278
279                name,
280                namespace,
281            }
282            .into_diag(dcx, level),
283            BuiltinLintDiag::UnusedQualifications { removal_span } => {
284                lints::UnusedQualifications { removal_span }.into_diag(dcx, level)
285            }
286            BuiltinLintDiag::AssociatedConstElidedLifetime {
287                elided,
288                span: lt_span,
289                lifetimes_in_scope,
290            } => {
291                let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
292                let code = if elided { "'static " } else { "'static" };
293                lints::AssociatedConstElidedLifetime {
294                    span: lt_span,
295                    code,
296                    elided,
297                    lifetimes_in_scope,
298                }
299                .into_diag(dcx, level)
300            }
301            BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span {
302                Some(wildcard_span) => {
303                    lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }
304                        .into_diag(dcx, level)
305                }
306                None => lints::UnreachableCfgSelectPredicate { span }.into_diag(dcx, level),
307            },
308
309            BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
310                lints::UnusedCrateDependency { extern_crate, local_crate }.into_diag(dcx, level)
311            }
312            BuiltinLintDiag::UnusedVisibility(span) => {
313                lints::UnusedVisibility { span }.into_diag(dcx, level)
314            }
315            BuiltinLintDiag::AttributeLint(kind) => {
316                DecorateAttrLint { sess: self.sess, tcx: self.tcx, diagnostic: &kind }
317                    .into_diag(dcx, level)
318            }
319        }
320    }
321}
322
323/// This is a diagnostic struct that will decorate a `AttributeLintKind`
324/// Directly creating the lint structs is expensive, using this will only decorate the lint structs when needed.
325pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
326    pub sess: &'sess Session,
327    pub tcx: Option<TyCtxt<'tcx>>,
328    pub diagnostic: &'a AttributeLintKind,
329}
330
331impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
332    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
333        match self.diagnostic {
334            &AttributeLintKind::UnusedDuplicate { this, other, warning } => {
335                lints::UnusedDuplicate { this, other, warning }.into_diag(dcx, level)
336            }
337            AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => {
338                lints::IllFormedAttributeInput {
339                    num_suggestions: suggestions.len(),
340                    suggestions: DiagArgValue::StrListSepByAnd(
341                        suggestions.into_iter().map(|s| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", s))
    })format!("`{s}`").into()).collect(),
342                    ),
343                    has_docs: docs.is_some(),
344                    docs: docs.unwrap_or(""),
345                }
346                .into_diag(dcx, level)
347            }
348            AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
349                lints::EmptyAttributeList {
350                    attr_span: *first_span,
351                    attr_path: attr_path.clone(),
352                    valid_without_list: *valid_without_list,
353                }
354                .into_diag(dcx, level)
355            }
356            AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => {
357                lints::InvalidTargetLint {
358                    name: name.clone(),
359                    target,
360                    applied: DiagArgValue::StrListSepByAnd(
361                        applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
362                    ),
363                    only,
364                    attr_span: *attr_span,
365                }
366                .into_diag(dcx, level)
367            }
368            &AttributeLintKind::InvalidStyle {
369                ref name,
370                is_used_as_inner,
371                target,
372                target_span,
373            } => lints::InvalidAttrStyle {
374                name: name.clone(),
375                is_used_as_inner,
376                target_span: (!is_used_as_inner).then_some(target_span),
377                target,
378            }
379            .into_diag(dcx, level),
380            &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => {
381                lints::UnsafeAttrOutsideUnsafeLint {
382                    span: attribute_name_span,
383                    suggestion: sugg_spans.map(|(left, right)| {
384                        lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }
385                    }),
386                }
387                .into_diag(dcx, level)
388            }
389            &AttributeLintKind::UnexpectedCfgName(name, value) => {
390                check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
391                    .into_diag(dcx, level)
392            }
393            &AttributeLintKind::UnexpectedCfgValue(name, value) => {
394                check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
395                    .into_diag(dcx, level)
396            }
397            &AttributeLintKind::DuplicateDocAlias { first_definition } => {
398                lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level)
399            }
400
401            &AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
402                lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level)
403            }
404
405            &AttributeLintKind::AmbiguousDeriveHelpers => {
406                lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
407            }
408
409            &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
410                lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.into_diag(dcx, level)
411            }
412
413            &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => {
414                lints::DocAutoCfgHideShowExpectsList { attr_name }.into_diag(dcx, level)
415            }
416
417            &AttributeLintKind::DocInvalid => lints::DocInvalid.into_diag(dcx, level),
418
419            &AttributeLintKind::DocUnknownInclude { span, inner, value } => {
420                lints::DocUnknownInclude {
421                    inner,
422                    value,
423                    sugg: (span, Applicability::MaybeIncorrect),
424                }
425                .into_diag(dcx, level)
426            }
427
428            &AttributeLintKind::DocUnknownSpotlight { span } => {
429                lints::DocUnknownSpotlight { sugg_span: span }.into_diag(dcx, level)
430            }
431
432            &AttributeLintKind::DocUnknownPasses { name, span } => {
433                lints::DocUnknownPasses { name, note_span: span }.into_diag(dcx, level)
434            }
435
436            &AttributeLintKind::DocUnknownPlugins { span } => {
437                lints::DocUnknownPlugins { label_span: span }.into_diag(dcx, level)
438            }
439
440            &AttributeLintKind::DocUnknownAny { name } => {
441                lints::DocUnknownAny { name }.into_diag(dcx, level)
442            }
443
444            &AttributeLintKind::DocAutoCfgWrongLiteral => {
445                lints::DocAutoCfgWrongLiteral.into_diag(dcx, level)
446            }
447
448            &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level),
449
450            &AttributeLintKind::DocTestUnknown { name } => {
451                lints::DocTestUnknown { name }.into_diag(dcx, level)
452            }
453
454            &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level),
455
456            &AttributeLintKind::AttrCrateLevelOnly => {
457                lints::AttrCrateLevelOnly.into_diag(dcx, level)
458            }
459
460            &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
461                lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level)
462            }
463
464            &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
465                sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
466            }
467            .into_diag(dcx, level),
468
469            &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
470
471            &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
472
473            &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
474            &AttributeLintKind::MalformedOnUnimplementedAttr { span } => {
475                lints::MalformedOnUnimplementedAttrLint { span }.into_diag(dcx, level)
476            }
477            &AttributeLintKind::MalformedOnConstAttr { span } => {
478                lints::MalformedOnConstAttrLint { span }.into_diag(dcx, level)
479            }
480            AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
481                FormatWarning::PositionalArgument { .. } => {
482                    lints::DisallowedPositionalArgument.into_diag(dcx, level)
483                }
484                FormatWarning::InvalidSpecifier { .. } => {
485                    lints::InvalidFormatSpecifier.into_diag(dcx, level)
486                }
487            },
488            AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
489                lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
490            }
491            &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
492                lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
493                    .into_diag(dcx, level)
494            }
495            &AttributeLintKind::MissingOptionsForOnUnimplemented => {
496                lints::MissingOptionsForOnUnimplementedAttr.into_diag(dcx, level)
497            }
498            &AttributeLintKind::MissingOptionsForOnConst => {
499                lints::MissingOptionsForOnConstAttr.into_diag(dcx, level)
500            }
501        }
502    }
503}