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