rustc_attr_parsing/attributes/diagnostic/
on_unimplemented.rs1use rustc_hir::attrs::diagnostic::Directive;
2use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
3
4use crate::attributes::diagnostic::*;
5use crate::attributes::prelude::*;
6use crate::errors::DiagnosticOnUnimplementedOnlyForTraits;
7
8#[derive(#[automatically_derived]
impl ::core::default::Default for OnUnimplementedParser {
#[inline]
fn default() -> OnUnimplementedParser {
OnUnimplementedParser {
span: ::core::default::Default::default(),
directive: ::core::default::Default::default(),
}
}
}Default)]
9pub(crate) struct OnUnimplementedParser {
10 span: Option<Span>,
11 directive: Option<(Span, Directive)>,
12}
13
14impl OnUnimplementedParser {
15 fn parse<'sess>(&mut self, cx: &mut AcceptContext<'_, 'sess>, args: &ArgParser, mode: Mode) {
16 let span = cx.attr_span;
17 self.span = Some(span);
18
19 if !#[allow(non_exhaustive_omitted_patterns)] match cx.target {
Target::Trait => true,
_ => false,
}matches!(cx.target, Target::Trait) {
20 cx.emit_lint(
21 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
22 DiagnosticOnUnimplementedOnlyForTraits,
23 span,
24 );
25 return;
26 }
27
28 let Some(items) = parse_list(cx, args, mode) else { return };
29
30 if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
31 merge_directives(cx, &mut self.directive, (span, directive));
32 };
33 }
34}
35
36impl AttributeParser for OnUnimplementedParser {
37 const ATTRIBUTES: AcceptMapping<Self> = &[
38 (
39 &[sym::diagnostic, sym::on_unimplemented],
40 ::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 = "...""#]),
41 |this, cx, args| {
42 this.parse(cx, args, Mode::DiagnosticOnUnimplemented);
43 },
44 ),
45 (
46 &[sym::rustc_on_unimplemented],
47 ::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 = "...""#]),
48 |this, cx, args| {
49 this.parse(cx, args, Mode::RustcOnUnimplemented);
50 },
51 ),
52 ];
53 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
55
56 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
57 if let Some(_span) = self.span {
58 Some(AttributeKind::OnUnimplemented {
59 directive: self.directive.map(|d| Box::new(d.1)),
60 })
61 } else {
62 None
63 }
64 }
65}