Skip to main content

rustc_lint/early/
diagnostics.rs

1use std::any::Any;
2
3use rustc_data_structures::sync::DynSend;
4use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level};
5use rustc_hir::lints::{AttributeLintKind, FormatWarning};
6use rustc_middle::ty::TyCtxt;
7use rustc_session::Session;
8
9use crate::lints;
10
11mod check_cfg;
12
13pub struct DiagAndSess<'sess> {
14    pub callback: Box<
15        dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b, ()> + DynSend + 'static,
16    >,
17    pub sess: &'sess Session,
18}
19
20impl<'a> Diagnostic<'a, ()> for DiagAndSess<'_> {
21    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
22        (self.callback)(dcx, level, self.sess)
23    }
24}
25
26/// This is a diagnostic struct that will decorate a `AttributeLintKind`
27/// Directly creating the lint structs is expensive, using this will only decorate the lint structs when needed.
28pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
29    pub sess: &'sess Session,
30    pub tcx: Option<TyCtxt<'tcx>>,
31    pub diagnostic: &'a AttributeLintKind,
32}
33
34impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
35    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
36        match self.diagnostic {
37            &AttributeLintKind::UnexpectedCfgName(name, value) => {
38                check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
39                    .into_diag(dcx, level)
40            }
41            &AttributeLintKind::UnexpectedCfgValue(name, value) => {
42                check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
43                    .into_diag(dcx, level)
44            }
45
46            &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level),
47
48            &AttributeLintKind::DocTestUnknown { name } => {
49                lints::DocTestUnknown { name }.into_diag(dcx, level)
50            }
51
52            &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level),
53
54            &AttributeLintKind::AttrCrateLevelOnly => {
55                lints::AttrCrateLevelOnly.into_diag(dcx, level)
56            }
57
58            &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
59                lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level)
60            }
61
62            &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
63                sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
64            }
65            .into_diag(dcx, level),
66
67            &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
68
69            &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
70
71            &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
72            &AttributeLintKind::MalFormedDiagnosticAttribute { attribute, options, span } => {
73                lints::MalFormedDiagnosticAttributeLint { attribute, options, span }
74                    .into_diag(dcx, level)
75            }
76
77            AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
78                FormatWarning::PositionalArgument { .. } => {
79                    lints::DisallowedPositionalArgument.into_diag(dcx, level)
80                }
81                FormatWarning::InvalidSpecifier { .. } => {
82                    lints::InvalidFormatSpecifier.into_diag(dcx, level)
83                }
84                FormatWarning::DisallowedPlaceholder { .. } => {
85                    lints::DisallowedPlaceholder.into_diag(dcx, level)
86                }
87            },
88            AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
89                lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
90            }
91            &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
92                lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
93                    .into_diag(dcx, level)
94            }
95            &AttributeLintKind::MissingOptionsForDiagnosticAttribute { attribute, options } => {
96                lints::MissingOptionsForDiagnosticAttribute { attribute, options }
97                    .into_diag(dcx, level)
98            }
99            &AttributeLintKind::NonMetaItemDiagnosticAttribute => {
100                lints::NonMetaItemDiagnosticAttribute.into_diag(dcx, level)
101            }
102        }
103    }
104}