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