rustc_attr_parsing/attributes/
macro_attrs.rs1use rustc_errors::DiagArgValue;
2use rustc_hir::attrs::MacroUseArgs;
3
4use super::prelude::*;
5use crate::session_diagnostics::IllFormedAttributeInputLint;
6
7pub(crate) struct MacroEscapeParser;
8impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
9 const PATH: &[Symbol] = &[sym::macro_escape];
10 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
11 const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS;
12 const CREATE: fn(Span) -> AttributeKind = AttributeKind::MacroEscape;
13}
14
15#[derive(Default)]
20pub(crate) struct MacroUseParser {
21 state: MacroUseArgs,
22
23 uses_attr_spans: ThinVec<Span>,
25 first_span: Option<Span>,
28}
29
30const MACRO_USE_TEMPLATE: AttributeTemplate = template!(
31 Word, List: &["name1, name2, ..."],
32 "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute"
33);
34const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
35 Allow(Target::Mod),
36 Allow(Target::ExternCrate),
37 Allow(Target::Crate),
38 Error(Target::WherePredicate),
39]);
40
41impl<S: Stage> AttributeParser<S> for MacroUseParser {
42 const ATTRIBUTES: AcceptMapping<Self, S> = &[(
43 &[sym::macro_use],
44 MACRO_USE_TEMPLATE,
45 |group: &mut Self, cx: &mut AcceptContext<'_, '_, S>, args| {
46 let span = cx.attr_span;
47 group.first_span.get_or_insert(span);
48 match args {
49 ArgParser::NoArgs => {
50 match group.state {
51 MacroUseArgs::UseAll => {
52 let first_span = group.first_span.expect(
53 "State is UseAll is some so this is not the first attribute",
54 );
55 cx.warn_unused_duplicate(first_span, span);
57 }
58 MacroUseArgs::UseSpecific(_) => {
59 group.state = MacroUseArgs::UseAll;
60 group.first_span = Some(span);
61 for specific_use in group.uses_attr_spans.drain(..) {
63 cx.warn_unused_duplicate(span, specific_use);
64 }
65 }
66 }
67 }
68 ArgParser::List(list) => {
69 if list.is_empty() {
70 cx.warn_empty_attribute(list.span);
71 return;
72 }
73
74 match &mut group.state {
75 MacroUseArgs::UseAll => {
76 let first_span = group.first_span.expect(
77 "State is UseAll is some so this is not the first attribute",
78 );
79 cx.warn_unused_duplicate(first_span, span);
80 }
81 MacroUseArgs::UseSpecific(arguments) => {
82 group.uses_attr_spans.push(cx.attr_span);
84
85 for item in list.mixed() {
86 let Some(item) = item.meta_item() else {
87 cx.expected_identifier(item.span());
88 continue;
89 };
90 if let Err(err_span) = item.args().no_args() {
91 cx.expected_no_args(err_span);
92 continue;
93 }
94 let Some(item) = item.path().word() else {
95 cx.expected_identifier(item.span());
96 continue;
97 };
98 arguments.push(item);
99 }
100 }
101 }
102 }
103 ArgParser::NameValue(_) => {
104 let suggestions = MACRO_USE_TEMPLATE.suggestions(cx.attr_style, sym::macro_use);
105 cx.emit_err(IllFormedAttributeInputLint {
106 num_suggestions: suggestions.len(),
107 suggestions: DiagArgValue::StrListSepByAnd(
108 suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
109 ),
110 span,
111 });
112 }
113 }
114 },
115 )];
116 const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS;
117
118 fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
119 Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
120 }
121}
122
123pub(crate) struct AllowInternalUnsafeParser;
124
125impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
126 const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
127 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
128 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
129 Allow(Target::Fn),
130 Allow(Target::MacroDef),
131 Warn(Target::Field),
132 Warn(Target::Arm),
133 ]);
134 const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
135}