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