rustc_attr_parsing/attributes/
crate_level.rs1use rustc_hir::attrs::{CrateType, WindowsSubsystemKind};
2use rustc_hir::lints::AttributeLintKind;
3use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES;
4use rustc_span::Symbol;
5use rustc_span::edit_distance::find_best_match_for_name;
6
7use super::prelude::*;
8
9pub(crate) struct CrateNameParser;
10
11impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
12 const PATH: &[Symbol] = &[sym::crate_name];
13 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
14 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
15 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
16 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
17
18 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
19 let ArgParser::NameValue(n) = args else {
20 cx.expected_name_value(cx.attr_span, None);
21 return None;
22 };
23
24 let Some(name) = n.value_as_str() else {
25 cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
26 return None;
27 };
28
29 Some(AttributeKind::CrateName { name, name_span: n.value_span, attr_span: cx.attr_span })
30 }
31}
32
33pub(crate) struct CrateTypeParser;
34
35impl<S: Stage> CombineAttributeParser<S> for CrateTypeParser {
36 const PATH: &[Symbol] = &[sym::crate_type];
37 type Item = CrateType;
38 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::CrateType(items);
39
40 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
41
42 const TEMPLATE: AttributeTemplate =
43 ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["crate type"]),
docs: Some("https://doc.rust-lang.org/reference/linkage.html"),
}template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html");
44
45 fn extend(
46 cx: &mut AcceptContext<'_, '_, S>,
47 args: &ArgParser,
48 ) -> impl IntoIterator<Item = Self::Item> {
49 let ArgParser::NameValue(n) = args else {
50 cx.expected_name_value(cx.attr_span, None);
51 return None;
52 };
53
54 let Some(crate_type) = n.value_as_str() else {
55 cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
56 return None;
57 };
58
59 let Ok(crate_type) = crate_type.try_into() else {
60 if cx.shared.target == Target::Crate {
62 let candidate = find_best_match_for_name(
63 &CrateType::all_stable().iter().map(|(name, _)| *name).collect::<Vec<_>>(),
64 crate_type,
65 None,
66 );
67 cx.emit_lint(
68 UNKNOWN_CRATE_TYPES,
69 AttributeLintKind::CrateTypeUnknown {
70 span: n.value_span,
71 suggested: candidate,
72 },
73 n.value_span,
74 );
75 }
76 return None;
77 };
78
79 Some(crate_type)
80 }
81}
82
83pub(crate) struct RecursionLimitParser;
84
85impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
86 const PATH: &[Symbol] = &[sym::recursion_limit];
87 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
88 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
89 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["N"]),
docs: Some("https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"),
}template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
90 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
91
92 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
93 let ArgParser::NameValue(nv) = args else {
94 cx.expected_name_value(cx.attr_span, None);
95 return None;
96 };
97
98 Some(AttributeKind::RecursionLimit {
99 limit: cx.parse_limit_int(nv)?,
100 attr_span: cx.attr_span,
101 limit_span: nv.value_span,
102 })
103 }
104}
105
106pub(crate) struct MoveSizeLimitParser;
107
108impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
109 const PATH: &[Symbol] = &[sym::move_size_limit];
110 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
111 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
112 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["N"]),
docs: None,
}template!(NameValueStr: "N");
113 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
114
115 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
116 let ArgParser::NameValue(nv) = args else {
117 cx.expected_name_value(cx.attr_span, None);
118 return None;
119 };
120
121 Some(AttributeKind::MoveSizeLimit {
122 limit: cx.parse_limit_int(nv)?,
123 attr_span: cx.attr_span,
124 limit_span: nv.value_span,
125 })
126 }
127}
128
129pub(crate) struct TypeLengthLimitParser;
130
131impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
132 const PATH: &[Symbol] = &[sym::type_length_limit];
133 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
134 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
135 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["N"]),
docs: None,
}template!(NameValueStr: "N");
136 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
137
138 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
139 let ArgParser::NameValue(nv) = args else {
140 cx.expected_name_value(cx.attr_span, None);
141 return None;
142 };
143
144 Some(AttributeKind::TypeLengthLimit {
145 limit: cx.parse_limit_int(nv)?,
146 attr_span: cx.attr_span,
147 limit_span: nv.value_span,
148 })
149 }
150}
151
152pub(crate) struct PatternComplexityLimitParser;
153
154impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
155 const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
156 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
157 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
158 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["N"]),
docs: None,
}template!(NameValueStr: "N");
159 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
160
161 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
162 let ArgParser::NameValue(nv) = args else {
163 cx.expected_name_value(cx.attr_span, None);
164 return None;
165 };
166
167 Some(AttributeKind::PatternComplexityLimit {
168 limit: cx.parse_limit_int(nv)?,
169 attr_span: cx.attr_span,
170 limit_span: nv.value_span,
171 })
172 }
173}
174
175pub(crate) struct NoCoreParser;
176
177impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
178 const PATH: &[Symbol] = &[sym::no_core];
179 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
180 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
181 const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
182}
183
184pub(crate) struct NoStdParser;
185
186impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
187 const PATH: &[Symbol] = &[sym::no_std];
188 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
189 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
190 const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
191}
192
193pub(crate) struct NoMainParser;
194
195impl<S: Stage> NoArgsAttributeParser<S> for NoMainParser {
196 const PATH: &[Symbol] = &[sym::no_main];
197 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
198 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
199 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain;
200}
201
202pub(crate) struct RustcCoherenceIsCoreParser;
203
204impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
205 const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
206 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
207 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
208 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoherenceIsCore;
209}
210
211pub(crate) struct WindowsSubsystemParser;
212
213impl<S: Stage> SingleAttributeParser<S> for WindowsSubsystemParser {
214 const PATH: &[Symbol] = &[sym::windows_subsystem];
215 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
216 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
217 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
218 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["windows", "console"]),
docs: Some("https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"),
}template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");
219
220 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
221 let Some(nv) = args.name_value() else {
222 cx.expected_name_value(
223 args.span().unwrap_or(cx.inner_span),
224 Some(sym::windows_subsystem),
225 );
226 return None;
227 };
228
229 let kind = match nv.value_as_str() {
230 Some(sym::console) => WindowsSubsystemKind::Console,
231 Some(sym::windows) => WindowsSubsystemKind::Windows,
232 Some(_) | None => {
233 cx.expected_specific_argument_strings(nv.value_span, &[sym::console, sym::windows]);
234 return None;
235 }
236 };
237
238 Some(AttributeKind::WindowsSubsystem(kind, cx.attr_span))
239 }
240}
241
242pub(crate) struct PanicRuntimeParser;
243
244impl<S: Stage> NoArgsAttributeParser<S> for PanicRuntimeParser {
245 const PATH: &[Symbol] = &[sym::panic_runtime];
246 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
247 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
248 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime;
249}
250
251pub(crate) struct NeedsPanicRuntimeParser;
252
253impl<S: Stage> NoArgsAttributeParser<S> for NeedsPanicRuntimeParser {
254 const PATH: &[Symbol] = &[sym::needs_panic_runtime];
255 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
256 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
257 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime;
258}
259
260pub(crate) struct ProfilerRuntimeParser;
261
262impl<S: Stage> NoArgsAttributeParser<S> for ProfilerRuntimeParser {
263 const PATH: &[Symbol] = &[sym::profiler_runtime];
264 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
265 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
266 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime;
267}
268
269pub(crate) struct NoBuiltinsParser;
270
271impl<S: Stage> NoArgsAttributeParser<S> for NoBuiltinsParser {
272 const PATH: &[Symbol] = &[sym::no_builtins];
273 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
274 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
275 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins;
276}