1use std::path::PathBuf;
2
3use rustc_ast::{LitIntType, LitKind, MetaItemLit};
4use rustc_attr_ir::lang_items::LangItem;
5use rustc_attr_ir::{
6 BorrowckGraphvizFormatKind, CguFields, CguKind, RustcCleanAttribute, RustcCleanQueries,
7 RustcMirKind,
8};
9use rustc_data_structures::fx::FxHashMap;
10use rustc_feature::AttributeStability;
11use rustc_span::Symbol;
12
13use super::prelude::*;
14use super::util::parse_single_integer;
15use crate::diagnostics;
16use crate::diagnostics::{
17 AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange,
18 UnknownExternLangItem, UnknownLangItem,
19};
20
21pub(crate) struct RustcMainParser;
22
23impl NoArgsAttributeParser for RustcMainParser {
24 const PATH: &[Symbol] = &[sym::rustc_main];
25 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
26 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_main` attribute is used internally to specify test entry point function"],
}
}unstable!(
27 rustc_attrs,
28 "the `rustc_main` attribute is used internally to specify test entry point function"
29 );
30 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain;
31}
32
33pub(crate) struct RustcMustImplementOneOfParser;
34
35impl SingleAttributeParser for RustcMustImplementOneOfParser {
36 const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];
37 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
38 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_must_implement_one_of` attribute is used to change minimal complete definition of a trait. Its syntax and semantics are highly experimental and will be subject to change before stabilization"],
}
}unstable!(
39 rustc_attrs,
40 "the `rustc_must_implement_one_of` attribute is used to change minimal complete definition of a trait. Its syntax and semantics are highly experimental and will be subject to change before stabilization"
41 );
42 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["function1, function2, ..."]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["function1, function2, ..."]);
43 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
44 let list = cx.expect_list(args, cx.attr_span)?;
45
46 let mut fn_names = ThinVec::new();
47
48 let inputs: Vec<_> = list.mixed().collect();
49
50 if inputs.len() < 2 {
51 cx.adcx().expected_list_with_num_args_or_more(2, list.span);
52 return None;
53 }
54
55 let mut errored = false;
56 for argument in inputs {
57 let Some(meta) = argument.meta_item_no_args() else {
58 cx.adcx().expected_identifier(argument.span());
59 return None;
60 };
61
62 let Some(ident) = meta.ident() else {
63 cx.dcx()
64 .emit_err(diagnostics::MustBeNameOfAssociatedFunction { span: meta.span() });
65 errored = true;
66 continue;
67 };
68
69 fn_names.push(ident);
70 }
71 if errored {
72 return None;
73 }
74
75 if cx.target == Target::Trait {
76 let mut seen: FxHashMap<Symbol, Span> = FxHashMap::default();
78 for ident in &fn_names {
79 if let Some(dup) = seen.insert(ident.name, ident.span) {
80 cx.emit_err(diagnostics::FunctionNamesDuplicated {
81 spans: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[dup, ident.span]))vec![dup, ident.span],
82 });
83 }
84 }
85 }
86
87 Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names })
88 }
89}
90
91pub(crate) struct RustcNeverReturnsNullPtrParser;
92
93impl NoArgsAttributeParser for RustcNeverReturnsNullPtrParser {
94 const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr];
95 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
96 Allow(Target::Fn),
97 Allow(Target::Method(MethodKind::Inherent)),
98 Allow(Target::Method(MethodKind::Trait { body: false })),
99 Allow(Target::Method(MethodKind::Trait { body: true })),
100 Allow(Target::Method(MethodKind::TraitImpl)),
101 ]);
102 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
103
104 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr;
105}
106
107pub(crate) struct RustcPanicsWhenZeroParser;
108
109impl NoArgsAttributeParser for RustcPanicsWhenZeroParser {
110 const PATH: &[Symbol] = &[sym::rustc_panics_when_zero];
111 const ALLOWED_TARGETS: AllowedTargets<'_> =
112 AllowedTargets::AllowList(&[Allow(Target::ConstParam)]);
113 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
114
115 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPanicsWhenZero;
116}
117
118pub(crate) struct RustcNoImplicitAutorefsParser;
119
120impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser {
121 const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs];
122 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
123 Allow(Target::Fn),
124 Allow(Target::Method(MethodKind::Inherent)),
125 Allow(Target::Method(MethodKind::Trait { body: false })),
126 Allow(Target::Method(MethodKind::Trait { body: true })),
127 Allow(Target::Method(MethodKind::TraitImpl)),
128 ]);
129 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
130
131 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;
132}
133
134pub(crate) struct RustcLegacyConstGenericsParser;
135
136impl SingleAttributeParser for RustcLegacyConstGenericsParser {
137 const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];
138 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
139 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["N"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["N"]);
140 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
141
142 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
143 let meta_items = cx.expect_list(args, cx.attr_span)?;
144
145 let mut parsed_indexes = ThinVec::new();
146 let mut errored = false;
147
148 for possible_index in meta_items.mixed() {
149 if let MetaItemOrLitParser::Lit(MetaItemLit {
150 kind: LitKind::Int(index, LitIntType::Unsuffixed),
151 ..
152 }) = possible_index
153 {
154 parsed_indexes.push((index.0 as usize, possible_index.span()));
155 } else {
156 cx.adcx().expected_integer_literal(possible_index.span());
157 errored = true;
158 }
159 }
160 if errored {
161 return None;
162 } else if parsed_indexes.is_empty() {
163 cx.adcx().expected_at_least_one_argument(args.span()?);
164 return None;
165 }
166
167 Some(AttributeKind::RustcLegacyConstGenerics {
168 fn_indexes: parsed_indexes,
169 attr_span: cx.attr_span,
170 })
171 }
172}
173
174pub(crate) struct RustcInheritOverflowChecksParser;
175
176impl NoArgsAttributeParser for RustcInheritOverflowChecksParser {
177 const PATH: &[Symbol] = &[sym::rustc_inherit_overflow_checks];
178 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
179 Allow(Target::Fn),
180 Allow(Target::Method(MethodKind::Inherent)),
181 Allow(Target::Method(MethodKind::TraitImpl)),
182 Allow(Target::Closure),
183 ]);
184 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
185 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInheritOverflowChecks;
186}
187
188pub(crate) struct RustcLintOptDenyFieldAccessParser;
189
190impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser {
191 const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access];
192 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Field)]);
193 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: None,
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word);
194 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
195 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
196 let arg = cx.expect_single_element_list(args, cx.attr_span)?;
197 let lint_message = cx.expect_string_literal(arg)?;
198
199 Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message })
200 }
201}
202
203pub(crate) struct RustcLintOptTyParser;
204
205impl NoArgsAttributeParser for RustcLintOptTyParser {
206 const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty];
207 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
208 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
209 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy;
210}
211
212fn parse_cgu_fields(
213 cx: &mut AcceptContext<'_, '_>,
214 args: &ArgParser,
215 accepts_kind: bool,
216) -> Option<(Symbol, Symbol, Option<CguKind>)> {
217 let args = cx.expect_list(args, cx.attr_span)?;
218
219 let mut cfg = None::<(Symbol, Span)>;
220 let mut module = None::<(Symbol, Span)>;
221 let mut kind = None::<(Symbol, Span)>;
222
223 for arg in args.mixed() {
224 let Some((ident, arg)) = cx.expect_name_value(arg, arg.span(), None) else {
225 continue;
226 };
227
228 let res = match ident.name {
229 sym::cfg => &mut cfg,
230 sym::module => &mut module,
231 sym::kind if accepts_kind => &mut kind,
232 _ => {
233 cx.adcx().expected_specific_argument(
234 ident.span,
235 if accepts_kind {
236 &[sym::cfg, sym::module, sym::kind]
237 } else {
238 &[sym::cfg, sym::module]
239 },
240 );
241 continue;
242 }
243 };
244
245 let str = cx.expect_string_literal(arg)?;
246
247 if res.is_some() {
248 cx.adcx().duplicate_key(ident.span.to(arg.args_span()), ident.name);
249 continue;
250 }
251
252 *res = Some((str, arg.value_span));
253 }
254
255 let Some((cfg, _)) = cfg else {
256 cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::cfg });
257 return None;
258 };
259 let Some((module, _)) = module else {
260 cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::module });
261 return None;
262 };
263 let kind = if let Some((kind, span)) = kind {
264 Some(match kind {
265 sym::no => CguKind::No,
266 sym::pre_dash_lto => CguKind::PreDashLto,
267 sym::post_dash_lto => CguKind::PostDashLto,
268 sym::any => CguKind::Any,
269 _ => {
270 cx.adcx().expected_specific_argument_strings(
271 span,
272 &[sym::no, sym::pre_dash_lto, sym::post_dash_lto, sym::any],
273 );
274 return None;
275 }
276 })
277 } else {
278 if accepts_kind {
280 cx.emit_err(CguFieldsMissing {
281 span: args.span,
282 name: &cx.attr_path,
283 field: sym::kind,
284 });
285 return None;
286 };
287
288 None
289 };
290
291 Some((cfg, module, kind))
292}
293
294#[derive(#[automatically_derived]
impl ::core::default::Default for RustcCguTestAttributeParser {
#[inline]
fn default() -> Self {
Self { items: ::core::default::Default::default() }
}
}Default)]
295pub(crate) struct RustcCguTestAttributeParser {
296 items: ThinVec<(Span, CguFields)>,
297}
298
299impl AttributeParser for RustcCguTestAttributeParser {
300 const ATTRIBUTES: AcceptMapping<Self> = &[
301 (
302 &[sym::rustc_partition_reused],
303 crate::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", module = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", module = "...""#]),
304 {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs),
305 |this, cx, args| {
306 this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| {
307 (cx.attr_span, CguFields::PartitionReused { cfg, module })
308 }));
309 },
310 ),
311 (
312 &[sym::rustc_partition_codegened],
313 crate::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", module = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", module = "...""#]),
314 {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs),
315 |this, cx, args| {
316 this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| {
317 (cx.attr_span, CguFields::PartitionCodegened { cfg, module })
318 }));
319 },
320 ),
321 (
322 &[sym::rustc_expected_cgu_reuse],
323 crate::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", module = "...", kind = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]),
324 {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs),
325 |this, cx, args| {
326 this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| {
327 (cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() })
329 }));
330 },
331 ),
332 ];
333
334 const ALLOWED_TARGETS: AllowedTargets<'_> =
335 AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]);
336
337 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
338 Some(AttributeKind::RustcCguTestAttr(self.items))
339 }
340}
341
342pub(crate) struct RustcDeprecatedSafe2024Parser;
343
344impl SingleAttributeParser for RustcDeprecatedSafe2024Parser {
345 const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024];
346 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
347 Allow(Target::Fn),
348 Allow(Target::Method(MethodKind::Inherent)),
349 Allow(Target::Method(MethodKind::Trait { body: false })),
350 Allow(Target::Method(MethodKind::Trait { body: true })),
351 Allow(Target::Method(MethodKind::TraitImpl)),
352 ]);
353 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&[r#"audit_that = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"audit_that = "...""#]);
354 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
355
356 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
357 let single = cx.expect_single_element_list(args, cx.attr_span)?;
358
359 let (path, arg) = cx.expect_name_value(single, cx.attr_span, None)?;
360
361 if path.name != sym::audit_that {
362 cx.adcx().expected_specific_argument(path.span, &[sym::audit_that]);
363 return None;
364 };
365
366 let suggestion = cx.expect_string_literal(arg)?;
367
368 Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion })
369 }
370}
371
372pub(crate) struct RustcConversionSuggestionParser;
373
374impl NoArgsAttributeParser for RustcConversionSuggestionParser {
375 const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion];
376 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
377 Allow(Target::Fn),
378 Allow(Target::Method(MethodKind::Inherent)),
379 Allow(Target::Method(MethodKind::Trait { body: false })),
380 Allow(Target::Method(MethodKind::Trait { body: true })),
381 Allow(Target::Method(MethodKind::TraitImpl)),
382 ]);
383 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
384 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion;
385}
386
387pub(crate) struct RustcCaptureAnalysisParser;
388
389impl NoArgsAttributeParser for RustcCaptureAnalysisParser {
390 const PATH: &[Symbol] = &[sym::rustc_capture_analysis];
391 const ALLOWED_TARGETS: AllowedTargets<'_> =
392 AllowedTargets::AllowList(&[Allow(Target::Closure)]);
393 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
394 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis;
395}
396
397pub(crate) struct RustcTrivialFieldReadsParser;
398
399impl NoArgsAttributeParser for RustcTrivialFieldReadsParser {
400 const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads];
401 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
402 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
403 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads;
404}
405
406pub(crate) struct RustcNoMirInlineParser;
407
408impl NoArgsAttributeParser for RustcNoMirInlineParser {
409 const PATH: &[Symbol] = &[sym::rustc_no_mir_inline];
410 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
411 Allow(Target::Fn),
412 Allow(Target::Method(MethodKind::Inherent)),
413 Allow(Target::Method(MethodKind::Trait { body: false })),
414 Allow(Target::Method(MethodKind::Trait { body: true })),
415 Allow(Target::Method(MethodKind::TraitImpl)),
416 ]);
417 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
418 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline;
419}
420
421pub(crate) struct RustcNoWritableParser;
422
423impl NoArgsAttributeParser for RustcNoWritableParser {
424 const PATH: &[Symbol] = &[sym::rustc_no_writable];
425 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
426 Allow(Target::Fn),
427 Allow(Target::Closure),
428 Allow(Target::Method(MethodKind::Inherent)),
429 Allow(Target::Method(MethodKind::TraitImpl)),
430 Allow(Target::Method(MethodKind::Trait { body: true })),
431 ]);
432 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
433 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoWritable;
434}
435
436pub(crate) struct RustcLintQueryInstabilityParser;
437
438impl NoArgsAttributeParser for RustcLintQueryInstabilityParser {
439 const PATH: &[Symbol] = &[sym::rustc_lint_query_instability];
440 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
441 Allow(Target::Fn),
442 Allow(Target::Method(MethodKind::Inherent)),
443 Allow(Target::Method(MethodKind::Trait { body: false })),
444 Allow(Target::Method(MethodKind::Trait { body: true })),
445 Allow(Target::Method(MethodKind::TraitImpl)),
446 ]);
447 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
448 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability;
449}
450
451pub(crate) struct RustcRegionsParser;
452
453impl NoArgsAttributeParser for RustcRegionsParser {
454 const PATH: &[Symbol] = &[sym::rustc_regions];
455 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
456 Allow(Target::Fn),
457 Allow(Target::Method(MethodKind::Inherent)),
458 Allow(Target::Method(MethodKind::Trait { body: false })),
459 Allow(Target::Method(MethodKind::Trait { body: true })),
460 Allow(Target::Method(MethodKind::TraitImpl)),
461 ]);
462 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
463 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions;
464}
465
466pub(crate) struct RustcLintUntrackedQueryInformationParser;
467
468impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser {
469 const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information];
470 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
471 Allow(Target::Fn),
472 Allow(Target::Method(MethodKind::Inherent)),
473 Allow(Target::Method(MethodKind::Trait { body: false })),
474 Allow(Target::Method(MethodKind::Trait { body: true })),
475 Allow(Target::Method(MethodKind::TraitImpl)),
476 ]);
477 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
478 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;
479}
480
481pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;
482
483impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser {
484 const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];
485 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
486 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["N"]),
docs: None,
}template!(NameValueStr: "N");
487 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
488
489 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
490 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
491 Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))
492 }
493}
494
495pub(crate) struct RustcScalableVectorParser;
496
497impl SingleAttributeParser for RustcScalableVectorParser {
498 const PATH: &[Symbol] = &[sym::rustc_scalable_vector];
499 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
500 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: Some(&["count"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["count"]);
501 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
502
503 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
504 if args.as_no_args().is_ok() {
505 return Some(AttributeKind::RustcScalableVector { element_count: None });
506 }
507
508 let n = parse_single_integer(cx, args)?;
509 let Ok(n) = n.try_into() else {
510 cx.emit_err(RustcScalableVectorCountOutOfRange { span: cx.attr_span, n });
511 return None;
512 };
513 Some(AttributeKind::RustcScalableVector { element_count: Some(n) })
514 }
515}
516
517pub(crate) struct LangParser;
518
519impl SingleAttributeParser for LangParser {
520 const PATH: &[Symbol] = &[sym::lang];
521 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::ManuallyChecked;
522 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
523 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::lang_items;
AttributeStability::Unstable {
gate_name: rustc_span::sym::lang_items,
notes: &[],
}
}unstable!(lang_items);
524
525 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
526 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
527 let name = cx.expect_string_literal(nv)?;
528 let Some(lang_item) = LangItem::from_name(name) else {
529 cx.emit_err(UnknownLangItem { span: cx.attr_span, name });
530 return None;
531 };
532
533 if [Target::ForeignFn, Target::ForeignStatic, Target::ForeignMod].contains(&cx.target)
536 && !lang_item.is_weak()
537 {
538 cx.emit_err(UnknownExternLangItem { span: cx.attr_span, lang_item: lang_item.name() });
539 return None;
540 }
541
542 let allowed_targets: &[_] = &[Allow(lang_item.target())];
544 cx.check_target(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" = \"{0}\"", name))
})format!(" = \"{name}\""), &AllowedTargets::AllowList(allowed_targets));
545
546 Some(AttributeKind::Lang(lang_item))
547 }
548}
549
550pub(crate) struct RustcHasIncoherentInherentImplsParser;
551
552impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser {
553 const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls];
554 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
555 Allow(Target::Trait),
556 Allow(Target::Struct),
557 Allow(Target::Enum),
558 Allow(Target::Union),
559 Allow(Target::ForeignTy),
560 ]);
561 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
562 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
563}
564
565pub(crate) struct PanicHandlerParser;
566
567impl NoArgsAttributeParser for PanicHandlerParser {
568 const PATH: &[Symbol] = &[sym::panic_handler];
569 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
570 const STABILITY: AttributeStability = AttributeStability::Stable;
571 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Lang(LangItem::PanicImpl);
572}
573
574pub(crate) struct RustcNounwindParser;
575
576impl NoArgsAttributeParser for RustcNounwindParser {
577 const PATH: &[Symbol] = &[sym::rustc_nounwind];
578 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
579 Allow(Target::Fn),
580 Allow(Target::ForeignFn),
581 Allow(Target::Method(MethodKind::Inherent)),
582 Allow(Target::Method(MethodKind::TraitImpl)),
583 Allow(Target::Method(MethodKind::Trait { body: true })),
584 ]);
585 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
586 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind;
587}
588
589pub(crate) struct RustcOffloadKernelParser;
590
591impl NoArgsAttributeParser for RustcOffloadKernelParser {
592 const PATH: &[Symbol] = &[sym::rustc_offload_kernel];
593 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
594 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
595 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
596}
597
598pub(crate) struct RustcMirParser;
599
600impl CombineAttributeParser for RustcMirParser {
601 const PATH: &[Symbol] = &[sym::rustc_mir];
602
603 type Item = RustcMirKind;
604
605 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items);
606 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
607 Allow(Target::Fn),
608 Allow(Target::Method(MethodKind::Inherent)),
609 Allow(Target::Method(MethodKind::TraitImpl)),
610 Allow(Target::Method(MethodKind::Trait { body: false })),
611 Allow(Target::Method(MethodKind::Trait { body: true })),
612 ]);
613 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["arg1, arg2, ..."]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["arg1, arg2, ..."]);
614 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
615
616 fn extend(
617 cx: &mut AcceptContext<'_, '_>,
618 args: &ArgParser,
619 ) -> impl IntoIterator<Item = Self::Item> {
620 let Some(list) = cx.expect_list(args, cx.attr_span) else {
621 return ThinVec::new();
622 };
623
624 list.mixed()
625 .filter_map(|arg| arg.meta_item())
626 .filter_map(|mi| {
627 if let Some(ident) = mi.ident() {
628 match ident.name {
629 sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit),
630 sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit),
631 sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness),
632 sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow),
633 sym::borrowck_graphviz_postflow => {
634 let nv = cx.expect_name_value(
635 mi.args(),
636 mi.span(),
637 Some(sym::borrowck_graphviz_postflow),
638 )?;
639 let path = cx.expect_string_literal(nv)?;
640 let path = PathBuf::from(path.to_string());
641 if path.file_name().is_some() {
642 Some(RustcMirKind::BorrowckGraphvizPostflow { path })
643 } else {
644 cx.adcx().expected_filename_literal(nv.value_span);
645 None
646 }
647 }
648 sym::borrowck_graphviz_format => {
649 let nv = cx.expect_name_value(
650 mi.args(),
651 mi.span(),
652 Some(sym::borrowck_graphviz_format),
653 )?;
654 let Some(format) = nv.value_as_ident() else {
655 cx.adcx().expected_identifier(nv.value_span);
656 return None;
657 };
658 match format.name {
659 sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat {
660 format: BorrowckGraphvizFormatKind::TwoPhase,
661 }),
662 _ => {
663 cx.adcx()
664 .expected_specific_argument(format.span, &[sym::two_phase]);
665 None
666 }
667 }
668 }
669 _ => None,
670 }
671 } else {
672 None
673 }
674 })
675 .collect()
676 }
677}
678pub(crate) struct RustcNonConstTraitMethodParser;
679
680impl NoArgsAttributeParser for RustcNonConstTraitMethodParser {
681 const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method];
682 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
683 Allow(Target::Method(MethodKind::Trait { body: true })),
684 Allow(Target::Method(MethodKind::Trait { body: false })),
685 ]);
686 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_non_const_trait_method` attribute should only be used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const"],
}
}unstable!(
687 rustc_attrs,
688 "the `rustc_non_const_trait_method` attribute should only be used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const"
689 );
690 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;
691}
692
693pub(crate) struct RustcCleanParser;
694
695impl CombineAttributeParser for RustcCleanParser {
696 const PATH: &[Symbol] = &[sym::rustc_clean];
697
698 type Item = RustcCleanAttribute;
699
700 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items);
701 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
702 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
704 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
705 Allow(Target::AssocConst(AssocCtxt::Trait)),
706 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
707 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
708 Allow(Target::AssocTy(AssocCtxt::Trait)),
709 Allow(Target::Const),
710 Allow(Target::Enum),
711 Allow(Target::Expression),
712 Allow(Target::Field),
713 Allow(Target::Fn),
714 Allow(Target::ForeignMod),
715 Allow(Target::Impl { of_trait: false }),
716 Allow(Target::Impl { of_trait: true }),
717 Allow(Target::Method(MethodKind::Inherent)),
718 Allow(Target::Method(MethodKind::Trait { body: false })),
719 Allow(Target::Method(MethodKind::Trait { body: true })),
720 Allow(Target::Method(MethodKind::TraitImpl)),
721 Allow(Target::Mod),
722 Allow(Target::Static),
723 Allow(Target::Struct),
724 Allow(Target::Trait),
725 Allow(Target::TyAlias),
726 Allow(Target::Union),
727 ]);
729 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
730 const TEMPLATE: AttributeTemplate =
731 crate::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]);
732
733 fn extend(
734 cx: &mut AcceptContext<'_, '_>,
735 args: &ArgParser,
736 ) -> impl IntoIterator<Item = Self::Item> {
737 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
738 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
739 }
740 let list = cx.expect_list(args, cx.attr_span)?;
741
742 let mut except = None;
743 let mut loaded_from_disk = None;
744 let mut cfg = None;
745
746 for item in list.mixed() {
747 let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {
748 continue;
749 };
750 let value_span = value.value_span;
751 let Some(value) = cx.expect_string_literal(value) else {
752 continue;
753 };
754 match ident.name {
755 sym::cfg if cfg.is_some() => {
756 cx.adcx().duplicate_key(item.span(), sym::cfg);
757 }
758 sym::cfg => {
759 cfg = Some(value);
760 }
761 sym::except if except.is_some() => {
762 cx.adcx().duplicate_key(item.span(), sym::except);
763 }
764 sym::except => {
765 let entries =
766 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
767 except = Some(RustcCleanQueries { entries, span: value_span });
768 }
769 sym::loaded_from_disk if loaded_from_disk.is_some() => {
770 cx.adcx().duplicate_key(item.span(), sym::loaded_from_disk);
771 }
772 sym::loaded_from_disk => {
773 let entries =
774 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
775 loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span });
776 }
777 _ => {
778 cx.adcx().expected_specific_argument(
779 ident.span,
780 &[sym::cfg, sym::except, sym::loaded_from_disk],
781 );
782 }
783 }
784 }
785 let Some(cfg) = cfg else {
786 cx.adcx().expected_specific_argument(list.span, &[sym::cfg]);
787 return None;
788 };
789
790 Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk })
791 }
792}
793
794pub(crate) struct RustcIfThisChangedParser;
795
796impl SingleAttributeParser for RustcIfThisChangedParser {
797 const PATH: &[Symbol] = &[sym::rustc_if_this_changed];
798 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
799 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
801 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
802 Allow(Target::AssocConst(AssocCtxt::Trait)),
803 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
804 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
805 Allow(Target::AssocTy(AssocCtxt::Trait)),
806 Allow(Target::Const),
807 Allow(Target::Enum),
808 Allow(Target::Expression),
809 Allow(Target::Field),
810 Allow(Target::Fn),
811 Allow(Target::ForeignMod),
812 Allow(Target::Impl { of_trait: false }),
813 Allow(Target::Impl { of_trait: true }),
814 Allow(Target::Method(MethodKind::Inherent)),
815 Allow(Target::Method(MethodKind::Trait { body: false })),
816 Allow(Target::Method(MethodKind::Trait { body: true })),
817 Allow(Target::Method(MethodKind::TraitImpl)),
818 Allow(Target::Mod),
819 Allow(Target::Static),
820 Allow(Target::Struct),
821 Allow(Target::Trait),
822 Allow(Target::TyAlias),
823 Allow(Target::Union),
824 ]);
826 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["DepNode"]);
827 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
828
829 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
830 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
831 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
832 }
833 match args {
834 ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
835 ArgParser::List(list) => {
836 let item = cx.expect_single(list)?;
837 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
838 cx.adcx().expected_identifier(item.span());
839 return None;
840 };
841 Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name)))
842 }
843 ArgParser::NameValue(_) => {
844 let inner_span = cx.inner_span;
845 cx.adcx().expected_list_or_no_args(inner_span);
846 None
847 }
848 }
849 }
850}
851
852pub(crate) struct RustcThenThisWouldNeedParser;
853
854impl CombineAttributeParser for RustcThenThisWouldNeedParser {
855 const PATH: &[Symbol] = &[sym::rustc_then_this_would_need];
856 type Item = Ident;
857
858 const CONVERT: ConvertFn<Self::Item> =
859 |items, _span| AttributeKind::RustcThenThisWouldNeed(items);
860 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
861 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
863 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
864 Allow(Target::AssocConst(AssocCtxt::Trait)),
865 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
866 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
867 Allow(Target::AssocTy(AssocCtxt::Trait)),
868 Allow(Target::Const),
869 Allow(Target::Enum),
870 Allow(Target::Expression),
871 Allow(Target::Field),
872 Allow(Target::Fn),
873 Allow(Target::ForeignMod),
874 Allow(Target::Impl { of_trait: false }),
875 Allow(Target::Impl { of_trait: true }),
876 Allow(Target::Method(MethodKind::Inherent)),
877 Allow(Target::Method(MethodKind::Trait { body: false })),
878 Allow(Target::Method(MethodKind::Trait { body: true })),
879 Allow(Target::Method(MethodKind::TraitImpl)),
880 Allow(Target::Mod),
881 Allow(Target::Static),
882 Allow(Target::Struct),
883 Allow(Target::Trait),
884 Allow(Target::TyAlias),
885 Allow(Target::Union),
886 ]);
888 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["DepNode"]);
889 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
890
891 fn extend(
892 cx: &mut AcceptContext<'_, '_>,
893 args: &ArgParser,
894 ) -> impl IntoIterator<Item = Self::Item> {
895 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
896 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
897 }
898 let item = cx.expect_single_element_list(args, cx.attr_span)?;
899 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
900 cx.adcx().expected_identifier(item.span());
901 return None;
902 };
903 Some(ident)
904 }
905}
906
907pub(crate) struct RustcInsignificantDtorParser;
908
909impl NoArgsAttributeParser for RustcInsignificantDtorParser {
910 const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];
911 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
912 Allow(Target::Enum),
913 Allow(Target::Struct),
914 Allow(Target::ForeignTy),
915 ]);
916 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
917 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;
918}
919
920pub(crate) struct RustcEffectiveVisibilityParser;
921
922impl NoArgsAttributeParser for RustcEffectiveVisibilityParser {
923 const PATH: &[Symbol] = &[sym::rustc_effective_visibility];
924 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
925 Allow(Target::Use),
926 Allow(Target::Static),
927 Allow(Target::Const),
928 Allow(Target::Fn),
929 Allow(Target::Closure),
930 Allow(Target::Mod),
931 Allow(Target::ForeignMod),
932 Allow(Target::TyAlias),
933 Allow(Target::Enum),
934 Allow(Target::Variant),
935 Allow(Target::Struct),
936 Allow(Target::Field),
937 Allow(Target::Union),
938 Allow(Target::Trait),
939 Allow(Target::TraitAlias),
940 Allow(Target::Impl { of_trait: false }),
941 Allow(Target::Impl { of_trait: true }),
942 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
943 Allow(Target::AssocConst(AssocCtxt::Trait)),
944 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
945 Allow(Target::Method(MethodKind::Inherent)),
946 Allow(Target::Method(MethodKind::Trait { body: false })),
947 Allow(Target::Method(MethodKind::Trait { body: true })),
948 Allow(Target::Method(MethodKind::TraitImpl)),
949 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
950 Allow(Target::AssocTy(AssocCtxt::Trait)),
951 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
952 Allow(Target::ForeignFn),
953 Allow(Target::ForeignStatic),
954 Allow(Target::ForeignTy),
955 Allow(Target::MacroDef),
956 Allow(Target::PatField),
957 Allow(Target::Crate),
958 ]);
959 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
960 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;
961}
962
963pub(crate) struct RustcDiagnosticItemParser;
964
965impl SingleAttributeParser for RustcDiagnosticItemParser {
966 const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
967 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
968 Allow(Target::Trait),
969 Allow(Target::Struct),
970 Allow(Target::Enum),
971 Allow(Target::MacroDef),
972 Allow(Target::TyAlias),
973 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
974 Allow(Target::AssocConst(AssocCtxt::Trait)),
975 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
976 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
977 Allow(Target::AssocTy(AssocCtxt::Trait)),
978 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
979 Allow(Target::Fn),
980 Allow(Target::Const),
981 Allow(Target::Mod),
982 Allow(Target::Impl { of_trait: false }),
983 Allow(Target::Method(MethodKind::Inherent)),
984 Allow(Target::Method(MethodKind::Trait { body: false })),
985 Allow(Target::Method(MethodKind::Trait { body: true })),
986 Allow(Target::Method(MethodKind::TraitImpl)),
987 Allow(Target::Crate),
988 ]);
989 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
990 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_diagnostic_item` attribute allows the compiler to reference types from the standard library for diagnostic purposes"],
}
}unstable!(
991 rustc_attrs,
992 "the `rustc_diagnostic_item` attribute allows the compiler to reference types from the standard library for diagnostic purposes"
993 );
994
995 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
996 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
997 let value = cx.expect_string_literal(nv)?;
998 Some(AttributeKind::RustcDiagnosticItem(value))
999 }
1000}
1001
1002pub(crate) struct RustcDoNotConstCheckParser;
1003
1004impl NoArgsAttributeParser for RustcDoNotConstCheckParser {
1005 const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];
1006 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1007 Allow(Target::Fn),
1008 Allow(Target::Method(MethodKind::Inherent)),
1009 Allow(Target::Method(MethodKind::TraitImpl)),
1010 Allow(Target::Method(MethodKind::Trait { body: false })),
1011 Allow(Target::Method(MethodKind::Trait { body: true })),
1012 ]);
1013 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_do_not_const_check` attribute skips const-check for this function's body"],
}
}unstable!(
1014 rustc_attrs,
1015 "the `rustc_do_not_const_check` attribute skips const-check for this function's body"
1016 );
1017 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;
1018}
1019
1020pub(crate) struct RustcNonnullOptimizationGuaranteedParser;
1021
1022impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser {
1023 const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];
1024 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
1025 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_nonnull_optimization_guaranteed` attribute is just used to document guaranteed niche optimizations in the standard library",
"the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized"],
}
}unstable!(
1026 rustc_attrs,
1027 "the `rustc_nonnull_optimization_guaranteed` attribute is just used to document guaranteed niche optimizations in the standard library",
1028 "the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized"
1029 );
1030 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;
1031}
1032
1033pub(crate) struct RustcStrictCoherenceParser;
1034
1035impl NoArgsAttributeParser for RustcStrictCoherenceParser {
1036 const PATH: &[Symbol] = &[sym::rustc_strict_coherence];
1037 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1038 Allow(Target::Trait),
1039 Allow(Target::Struct),
1040 Allow(Target::Enum),
1041 Allow(Target::Union),
1042 Allow(Target::ForeignTy),
1043 ]);
1044 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
1045 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;
1046}
1047
1048pub(crate) struct PreludeImportParser;
1049
1050impl NoArgsAttributeParser for PreludeImportParser {
1051 const PATH: &[Symbol] = &[sym::prelude_import];
1052 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]);
1053 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::prelude_import;
AttributeStability::Unstable {
gate_name: rustc_span::sym::prelude_import,
notes: &[],
}
}unstable!(prelude_import);
1054 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;
1055}
1056
1057pub(crate) struct RustcDocPrimitiveParser;
1058
1059impl SingleAttributeParser for RustcDocPrimitiveParser {
1060 const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
1061 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Const)]);
1062 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["primitive name"]),
docs: None,
}template!(NameValueStr: "primitive name");
1063 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_doc_primitive` attribute is used by the standard library to provide a way to generate documentation for primitive types"],
}
}unstable!(
1064 rustc_attrs,
1065 "the `rustc_doc_primitive` attribute is used by the standard library to provide a way to generate documentation for primitive types"
1066 );
1067
1068 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
1069 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
1070 let value_str = cx.expect_string_literal(nv)?;
1071
1072 Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))
1073 }
1074}
1075
1076pub(crate) struct RustcIntrinsicParser;
1077
1078impl NoArgsAttributeParser for RustcIntrinsicParser {
1079 const PATH: &[Symbol] = &[sym::rustc_intrinsic];
1080 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1081 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::intrinsics;
AttributeStability::Unstable {
gate_name: rustc_span::sym::intrinsics,
notes: &[],
}
}unstable!(intrinsics);
1082 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;
1083}
1084
1085pub(crate) struct RustcIntrinsicConstStableIndirectParser;
1086
1087impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser {
1088 const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
1089 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1090 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
1091 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
1092}
1093
1094pub(crate) struct RustcExhaustiveParser;
1095
1096impl NoArgsAttributeParser for RustcExhaustiveParser {
1097 const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];
1098 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Enum)]);
1099 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &[],
}
}unstable!(rustc_attrs);
1100 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively;
1101}
1102
1103pub(crate) struct RustcCanonicalSymbolParser;
1104
1105impl NoArgsAttributeParser for RustcCanonicalSymbolParser {
1106 const PATH: &[Symbol] = &[sym::rustc_canonical_symbol];
1107 const ALLOWED_TARGETS: AllowedTargets<'_> =
1108 AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
1109 const STABILITY: AttributeStability = {
_ = rustc_feature::Features::rustc_attrs;
AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
notes: &["the `rustc_canonical_symbol` attribute registers a function's symbol to be linted against \
by the `invalid_runtime_symbol_definitions` and `suspicious_runtime_symbol_definitions` \
lints"],
}
}unstable!(
1110 rustc_attrs,
1111 "the `rustc_canonical_symbol` attribute registers a function's symbol to be linted against \
1112 by the `invalid_runtime_symbol_definitions` and `suspicious_runtime_symbol_definitions` \
1113 lints"
1114 );
1115 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCanonicalSymbol;
1116}