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::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}