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