Skip to main content

rustc_attr_parsing/attributes/diagnostic/
on_unknown.rs

1use rustc_hir::attrs::diagnostic::Directive;
2use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
3
4use crate::attributes::diagnostic::*;
5use crate::attributes::prelude::*;
6
7#[derive(#[automatically_derived]
impl ::core::default::Default for OnUnknownParser {
    #[inline]
    fn default() -> OnUnknownParser {
        OnUnknownParser {
            span: ::core::default::Default::default(),
            directive: ::core::default::Default::default(),
        }
    }
}Default)]
8pub(crate) struct OnUnknownParser {
9    span: Option<Span>,
10    directive: Option<(Span, Directive)>,
11}
12
13impl OnUnknownParser {
14    fn parse<'sess, S: Stage>(
15        &mut self,
16        cx: &mut AcceptContext<'_, 'sess, S>,
17        args: &ArgParser,
18        mode: Mode,
19    ) {
20        if !cx.features().diagnostic_on_unknown() {
21            return;
22        }
23        let span = cx.attr_span;
24        self.span = Some(span);
25
26        let items = match args {
27            ArgParser::List(items) if !items.is_empty() => items,
28            ArgParser::NoArgs | ArgParser::List(_) => {
29                cx.emit_lint(
30                    MALFORMED_DIAGNOSTIC_ATTRIBUTES,
31                    AttributeLintKind::MissingOptionsForOnUnknown,
32                    span,
33                );
34                return;
35            }
36            ArgParser::NameValue(_) => {
37                cx.emit_lint(
38                    MALFORMED_DIAGNOSTIC_ATTRIBUTES,
39                    AttributeLintKind::MalformedOnUnknownAttr { span },
40                    span,
41                );
42                return;
43            }
44        };
45
46        if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
47            merge_directives(cx, &mut self.directive, (span, directive));
48        };
49    }
50}
51
52impl<S: Stage> AttributeParser<S> for OnUnknownParser {
53    const ATTRIBUTES: AcceptMapping<Self, S> = &[(
54        &[sym::diagnostic, sym::on_unknown],
55        ::rustc_feature::AttributeTemplate {
    word: false,
    list: Some(&[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
    one_of: &[],
    name_value_str: None,
    docs: None,
}template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
56        |this, cx, args| {
57            this.parse(cx, args, Mode::DiagnosticOnUnknown);
58        },
59    )];
60    //FIXME attribute is not parsed for non-use statements but diagnostics are issued in `check_attr.rs`
61    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
62
63    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
64        if let Some(span) = self.span {
65            Some(AttributeKind::OnUnknown {
66                span,
67                directive: self.directive.map(|d| Box::new(d.1)),
68            })
69        } else {
70            None
71        }
72    }
73}