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