Skip to main content

rustc_lint/early/
diagnostics.rs

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
27/// This is a diagnostic struct that will decorate a `AttributeLintKind`
28/// Directly creating the lint structs is expensive, using this will only decorate the lint structs when needed.
29pub 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::IllFormedAttributeInput { suggestions, docs, help } => {
39                lints::IllFormedAttributeInput {
40                    num_suggestions: suggestions.len(),
41                    suggestions: DiagArgValue::StrListSepByAnd(
42                        suggestions.into_iter().map(|s| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", s))
    })format!("`{s}`").into()).collect(),
43                    ),
44                    has_docs: docs.is_some(),
45                    docs: docs.unwrap_or(""),
46                    help: help.clone().map(|h| lints::IllFormedAttributeInputHelp { lint: h }),
47                }
48                .into_diag(dcx, level)
49            }
50            AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
51                lints::EmptyAttributeList {
52                    attr_span: *first_span,
53                    attr_path: attr_path.clone(),
54                    valid_without_list: *valid_without_list,
55                }
56                .into_diag(dcx, level)
57            }
58            AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => {
59                lints::InvalidTargetLint {
60                    name: name.clone(),
61                    target,
62                    applied: DiagArgValue::StrListSepByAnd(
63                        applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
64                    ),
65                    only,
66                    attr_span: *attr_span,
67                }
68                .into_diag(dcx, level)
69            }
70            &AttributeLintKind::InvalidStyle {
71                ref name,
72                is_used_as_inner,
73                target,
74                target_span,
75            } => lints::InvalidAttrStyle {
76                name: name.clone(),
77                is_used_as_inner,
78                target_span: (!is_used_as_inner).then_some(target_span),
79                target,
80            }
81            .into_diag(dcx, level),
82            &AttributeLintKind::UnexpectedCfgName(name, value) => {
83                check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
84                    .into_diag(dcx, level)
85            }
86            &AttributeLintKind::UnexpectedCfgValue(name, value) => {
87                check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
88                    .into_diag(dcx, level)
89            }
90            &AttributeLintKind::DuplicateDocAlias { first_definition } => {
91                lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level)
92            }
93
94            &AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
95                lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level)
96            }
97
98            &AttributeLintKind::AmbiguousDeriveHelpers => {
99                lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
100            }
101
102            &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
103                lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.into_diag(dcx, level)
104            }
105
106            &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => {
107                lints::DocAutoCfgHideShowExpectsList { attr_name }.into_diag(dcx, level)
108            }
109
110            &AttributeLintKind::DocInvalid => lints::DocInvalid.into_diag(dcx, level),
111
112            &AttributeLintKind::DocUnknownInclude { span, inner, value } => {
113                lints::DocUnknownInclude {
114                    inner,
115                    value,
116                    sugg: (span, Applicability::MaybeIncorrect),
117                }
118                .into_diag(dcx, level)
119            }
120
121            &AttributeLintKind::DocUnknownSpotlight { span } => {
122                lints::DocUnknownSpotlight { sugg_span: span }.into_diag(dcx, level)
123            }
124
125            &AttributeLintKind::DocUnknownPasses { name, span } => {
126                lints::DocUnknownPasses { name, note_span: span }.into_diag(dcx, level)
127            }
128
129            &AttributeLintKind::DocUnknownPlugins { span } => {
130                lints::DocUnknownPlugins { label_span: span }.into_diag(dcx, level)
131            }
132
133            &AttributeLintKind::DocUnknownAny { name } => {
134                lints::DocUnknownAny { name }.into_diag(dcx, level)
135            }
136
137            &AttributeLintKind::DocAutoCfgWrongLiteral => {
138                lints::DocAutoCfgWrongLiteral.into_diag(dcx, level)
139            }
140
141            &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level),
142
143            &AttributeLintKind::DocTestUnknown { name } => {
144                lints::DocTestUnknown { name }.into_diag(dcx, level)
145            }
146
147            &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level),
148
149            &AttributeLintKind::AttrCrateLevelOnly => {
150                lints::AttrCrateLevelOnly.into_diag(dcx, level)
151            }
152
153            &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
154                lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level)
155            }
156
157            &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
158                sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
159            }
160            .into_diag(dcx, level),
161
162            &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
163
164            &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
165
166            &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
167            &AttributeLintKind::MalFormedDiagnosticAttribute { attribute, options, span } => {
168                lints::MalFormedDiagnosticAttributeLint { attribute, options, span }
169                    .into_diag(dcx, level)
170            }
171
172            AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
173                FormatWarning::PositionalArgument { .. } => {
174                    lints::DisallowedPositionalArgument.into_diag(dcx, level)
175                }
176                FormatWarning::InvalidSpecifier { .. } => {
177                    lints::InvalidFormatSpecifier.into_diag(dcx, level)
178                }
179                FormatWarning::DisallowedPlaceholder { .. } => {
180                    lints::DisallowedPlaceholder.into_diag(dcx, level)
181                }
182            },
183            AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
184                lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
185            }
186            &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
187                lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
188                    .into_diag(dcx, level)
189            }
190            &AttributeLintKind::MissingOptionsForDiagnosticAttribute { attribute, options } => {
191                lints::MissingOptionsForDiagnosticAttribute { attribute, options }
192                    .into_diag(dcx, level)
193            }
194            &AttributeLintKind::NonMetaItemDiagnosticAttribute => {
195                lints::NonMetaItemDiagnosticAttribute.into_diag(dcx, level)
196            }
197        }
198    }
199}