rustc_attr_parsing/attributes/
rustc_internal.rs1use rustc_ast::{LitIntType, LitKind, MetaItemLit};
2use rustc_session::errors;
3
4use super::prelude::*;
5use super::util::parse_single_integer;
6use crate::session_diagnostics::RustcScalableVectorCountOutOfRange;
7
8pub(crate) struct RustcMainParser;
9
10impl<S: Stage> NoArgsAttributeParser<S> for RustcMainParser {
11 const PATH: &'static [Symbol] = &[sym::rustc_main];
12 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
13 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
14 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain;
15}
16
17pub(crate) struct RustcMustImplementOneOfParser;
18
19impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
20 const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];
21 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
22 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
23 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
24 const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);
25 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
26 let Some(list) = args.list() else {
27 cx.expected_list(cx.attr_span, args);
28 return None;
29 };
30
31 let mut fn_names = ThinVec::new();
32
33 let inputs: Vec<_> = list.mixed().collect();
34
35 if inputs.len() < 2 {
36 cx.expected_list_with_num_args_or_more(2, list.span);
37 return None;
38 }
39
40 let mut errored = false;
41 for argument in inputs {
42 let Some(meta) = argument.meta_item() else {
43 cx.expected_identifier(argument.span());
44 return None;
45 };
46
47 let Some(ident) = meta.ident() else {
48 cx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span: meta.span() });
49 errored = true;
50 continue;
51 };
52
53 fn_names.push(ident);
54 }
55 if errored {
56 return None;
57 }
58
59 Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names })
60 }
61}
62
63pub(crate) struct RustcNeverReturnsNullPointerParser;
64
65impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPointerParser {
66 const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr];
67 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
68 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
69 Allow(Target::Fn),
70 Allow(Target::Method(MethodKind::Inherent)),
71 Allow(Target::Method(MethodKind::Trait { body: false })),
72 Allow(Target::Method(MethodKind::Trait { body: true })),
73 Allow(Target::Method(MethodKind::TraitImpl)),
74 ]);
75 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPointer;
76}
77pub(crate) struct RustcNoImplicitAutorefsParser;
78
79impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitAutorefsParser {
80 const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs];
81 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
82 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
83 Allow(Target::Fn),
84 Allow(Target::Method(MethodKind::Inherent)),
85 Allow(Target::Method(MethodKind::Trait { body: false })),
86 Allow(Target::Method(MethodKind::Trait { body: true })),
87 Allow(Target::Method(MethodKind::TraitImpl)),
88 ]);
89
90 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;
91}
92
93pub(crate) struct RustcLayoutScalarValidRangeStartParser;
94
95impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStartParser {
96 const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
97 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
98 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
99 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
100 const TEMPLATE: AttributeTemplate = template!(List: &["start"]);
101
102 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
103 parse_single_integer(cx, args)
104 .map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(Box::new(n), cx.attr_span))
105 }
106}
107
108pub(crate) struct RustcLayoutScalarValidRangeEndParser;
109
110impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEndParser {
111 const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
112 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
113 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
114 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
115 const TEMPLATE: AttributeTemplate = template!(List: &["end"]);
116
117 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
118 parse_single_integer(cx, args)
119 .map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(Box::new(n), cx.attr_span))
120 }
121}
122
123pub(crate) struct RustcLegacyConstGenericsParser;
124
125impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
126 const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];
127 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
128 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
129 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
130 const TEMPLATE: AttributeTemplate = template!(List: &["N"]);
131
132 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
133 let ArgParser::List(meta_items) = args else {
134 cx.expected_list(cx.attr_span, args);
135 return None;
136 };
137
138 let mut parsed_indexes = ThinVec::new();
139 let mut errored = false;
140
141 for possible_index in meta_items.mixed() {
142 if let MetaItemOrLitParser::Lit(MetaItemLit {
143 kind: LitKind::Int(index, LitIntType::Unsuffixed),
144 ..
145 }) = possible_index
146 {
147 parsed_indexes.push((index.0 as usize, possible_index.span()));
148 } else {
149 cx.expected_integer_literal(possible_index.span());
150 errored = true;
151 }
152 }
153 if errored {
154 return None;
155 } else if parsed_indexes.is_empty() {
156 cx.expected_at_least_one_argument(args.span()?);
157 return None;
158 }
159
160 Some(AttributeKind::RustcLegacyConstGenerics {
161 fn_indexes: parsed_indexes,
162 attr_span: cx.attr_span,
163 })
164 }
165}
166
167pub(crate) struct RustcLintDiagnosticsParser;
168
169impl<S: Stage> NoArgsAttributeParser<S> for RustcLintDiagnosticsParser {
170 const PATH: &[Symbol] = &[sym::rustc_lint_diagnostics];
171 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
172 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
173 Allow(Target::Fn),
174 Allow(Target::Method(MethodKind::Inherent)),
175 Allow(Target::Method(MethodKind::Trait { body: false })),
176 Allow(Target::Method(MethodKind::Trait { body: true })),
177 Allow(Target::Method(MethodKind::TraitImpl)),
178 ]);
179 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintDiagnostics;
180}
181
182pub(crate) struct RustcLintOptDenyFieldAccessParser;
183
184impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
185 const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access];
186 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
187 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
188 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]);
189 const TEMPLATE: AttributeTemplate = template!(Word);
190 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
191 let Some(arg) = args.list().and_then(MetaItemListParser::single) else {
192 cx.expected_single_argument(cx.attr_span);
193 return None;
194 };
195
196 let MetaItemOrLitParser::Lit(MetaItemLit { kind: LitKind::Str(lint_message, _), .. }) = arg
197 else {
198 cx.expected_string_literal(arg.span(), arg.lit());
199 return None;
200 };
201
202 Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message: *lint_message })
203 }
204}
205
206pub(crate) struct RustcLintOptTyParser;
207
208impl<S: Stage> NoArgsAttributeParser<S> for RustcLintOptTyParser {
209 const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty];
210 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
211 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
212 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy;
213}
214
215pub(crate) struct RustcLintQueryInstabilityParser;
216
217impl<S: Stage> NoArgsAttributeParser<S> for RustcLintQueryInstabilityParser {
218 const PATH: &[Symbol] = &[sym::rustc_lint_query_instability];
219 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
220 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
221 Allow(Target::Fn),
222 Allow(Target::Method(MethodKind::Inherent)),
223 Allow(Target::Method(MethodKind::Trait { body: false })),
224 Allow(Target::Method(MethodKind::Trait { body: true })),
225 Allow(Target::Method(MethodKind::TraitImpl)),
226 ]);
227 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability;
228}
229
230pub(crate) struct RustcLintUntrackedQueryInformationParser;
231
232impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationParser {
233 const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information];
234 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
235 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
236 Allow(Target::Fn),
237 Allow(Target::Method(MethodKind::Inherent)),
238 Allow(Target::Method(MethodKind::Trait { body: false })),
239 Allow(Target::Method(MethodKind::Trait { body: true })),
240 Allow(Target::Method(MethodKind::TraitImpl)),
241 ]);
242
243 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;
244}
245
246pub(crate) struct RustcObjectLifetimeDefaultParser;
247
248impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
249 const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default];
250 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
251 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
252 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
253 const TEMPLATE: AttributeTemplate = template!(Word);
254
255 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
256 if let Err(span) = args.no_args() {
257 cx.expected_no_args(span);
258 return None;
259 }
260
261 Some(AttributeKind::RustcObjectLifetimeDefault)
262 }
263}
264
265pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;
266
267impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser {
268 const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];
269 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
270 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
271 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
272 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
273
274 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
275 let ArgParser::NameValue(nv) = args else {
276 cx.expected_name_value(cx.attr_span, None);
277 return None;
278 };
279 Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))
280 }
281}
282
283pub(crate) struct RustcScalableVectorParser;
284
285impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
286 const PATH: &[rustc_span::Symbol] = &[sym::rustc_scalable_vector];
287 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
288 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
289 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
290 const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);
291
292 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
293 if args.no_args().is_ok() {
294 return Some(AttributeKind::RustcScalableVector {
295 element_count: None,
296 span: cx.attr_span,
297 });
298 }
299
300 let n = parse_single_integer(cx, args)?;
301 let Ok(n) = n.try_into() else {
302 cx.emit_err(RustcScalableVectorCountOutOfRange { span: cx.attr_span, n });
303 return None;
304 };
305 Some(AttributeKind::RustcScalableVector { element_count: Some(n), span: cx.attr_span })
306 }
307}