1use std::path::PathBuf;
2
3use rustc_ast::{LitIntType, LitKind, MetaItemLit};
4use rustc_attr_ir::lang_items::LangItem;
5use rustc_attr_ir::target::GenericParamKind;
6use rustc_attr_ir::{
7 BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,
8 DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcMirKind,
9};
10use rustc_data_structures::fx::FxHashMap;
11use rustc_feature::AttributeStability;
12use rustc_span::Symbol;
13
14use super::prelude::*;
15use super::util::parse_single_integer;
16use crate::diagnostics;
17use crate::diagnostics::{
18 AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange,
19 UnknownExternLangItem, 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::ForeignMod].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(AssocCtxt::Impl { of_trait: false })),
781 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
782 Allow(Target::AssocConst(AssocCtxt::Trait)),
783 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
784 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
785 Allow(Target::AssocTy(AssocCtxt::Trait)),
786 Allow(Target::Const),
787 Allow(Target::Enum),
788 Allow(Target::Expression),
789 Allow(Target::Field),
790 Allow(Target::Fn),
791 Allow(Target::ForeignMod),
792 Allow(Target::Impl { of_trait: false }),
793 Allow(Target::Impl { of_trait: true }),
794 Allow(Target::Method(MethodKind::Inherent)),
795 Allow(Target::Method(MethodKind::Trait { body: false })),
796 Allow(Target::Method(MethodKind::Trait { body: true })),
797 Allow(Target::Method(MethodKind::TraitImpl)),
798 Allow(Target::Mod),
799 Allow(Target::Static),
800 Allow(Target::Struct),
801 Allow(Target::Trait),
802 Allow(Target::TyAlias),
803 Allow(Target::Union),
804 ]);
806 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
807 const TEMPLATE: AttributeTemplate =
808 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 = "...""#]);
809
810 fn extend(
811 cx: &mut AcceptContext<'_, '_>,
812 args: &ArgParser,
813 ) -> impl IntoIterator<Item = Self::Item> {
814 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
815 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
816 }
817 let list = cx.expect_list(args, cx.attr_span)?;
818
819 let mut except = None;
820 let mut loaded_from_disk = None;
821 let mut cfg = None;
822
823 for item in list.mixed() {
824 let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {
825 continue;
826 };
827 let value_span = value.value_span;
828 let Some(value) = cx.expect_string_literal(value) else {
829 continue;
830 };
831 match ident.name {
832 sym::cfg if cfg.is_some() => {
833 cx.adcx().duplicate_key(item.span(), sym::cfg);
834 }
835 sym::cfg => {
836 cfg = Some(value);
837 }
838 sym::except if except.is_some() => {
839 cx.adcx().duplicate_key(item.span(), sym::except);
840 }
841 sym::except => {
842 let entries =
843 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
844 except = Some(RustcCleanQueries { entries, span: value_span });
845 }
846 sym::loaded_from_disk if loaded_from_disk.is_some() => {
847 cx.adcx().duplicate_key(item.span(), sym::loaded_from_disk);
848 }
849 sym::loaded_from_disk => {
850 let entries =
851 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
852 loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span });
853 }
854 _ => {
855 cx.adcx().expected_specific_argument(
856 ident.span,
857 &[sym::cfg, sym::except, sym::loaded_from_disk],
858 );
859 }
860 }
861 }
862 let Some(cfg) = cfg else {
863 cx.adcx().expected_specific_argument(list.span, &[sym::cfg]);
864 return None;
865 };
866
867 Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk })
868 }
869}
870
871pub(crate) struct RustcIfThisChangedParser;
872
873impl SingleAttributeParser for RustcIfThisChangedParser {
874 const PATH: &[Symbol] = &[sym::rustc_if_this_changed];
875 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
876 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
878 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
879 Allow(Target::AssocConst(AssocCtxt::Trait)),
880 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
881 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
882 Allow(Target::AssocTy(AssocCtxt::Trait)),
883 Allow(Target::Const),
884 Allow(Target::Enum),
885 Allow(Target::Expression),
886 Allow(Target::Field),
887 Allow(Target::Fn),
888 Allow(Target::ForeignMod),
889 Allow(Target::Impl { of_trait: false }),
890 Allow(Target::Impl { of_trait: true }),
891 Allow(Target::Method(MethodKind::Inherent)),
892 Allow(Target::Method(MethodKind::Trait { body: false })),
893 Allow(Target::Method(MethodKind::Trait { body: true })),
894 Allow(Target::Method(MethodKind::TraitImpl)),
895 Allow(Target::Mod),
896 Allow(Target::Static),
897 Allow(Target::Struct),
898 Allow(Target::Trait),
899 Allow(Target::TyAlias),
900 Allow(Target::Union),
901 ]);
903 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["DepNode"]);
904 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
905
906 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
907 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
908 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
909 }
910 match args {
911 ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
912 ArgParser::List(list) => {
913 let item = cx.expect_single(list)?;
914 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
915 cx.adcx().expected_identifier(item.span());
916 return None;
917 };
918 Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name)))
919 }
920 ArgParser::NameValue(_) => {
921 let inner_span = cx.inner_span;
922 cx.adcx().expected_list_or_no_args(inner_span);
923 None
924 }
925 }
926 }
927}
928
929pub(crate) struct RustcThenThisWouldNeedParser;
930
931impl CombineAttributeParser for RustcThenThisWouldNeedParser {
932 const PATH: &[Symbol] = &[sym::rustc_then_this_would_need];
933 type Item = Ident;
934
935 const CONVERT: ConvertFn<Self::Item> =
936 |items, _span| AttributeKind::RustcThenThisWouldNeed(items);
937 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
938 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
940 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
941 Allow(Target::AssocConst(AssocCtxt::Trait)),
942 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
943 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
944 Allow(Target::AssocTy(AssocCtxt::Trait)),
945 Allow(Target::Const),
946 Allow(Target::Enum),
947 Allow(Target::Expression),
948 Allow(Target::Field),
949 Allow(Target::Fn),
950 Allow(Target::ForeignMod),
951 Allow(Target::Impl { of_trait: false }),
952 Allow(Target::Impl { of_trait: true }),
953 Allow(Target::Method(MethodKind::Inherent)),
954 Allow(Target::Method(MethodKind::Trait { body: false })),
955 Allow(Target::Method(MethodKind::Trait { body: true })),
956 Allow(Target::Method(MethodKind::TraitImpl)),
957 Allow(Target::Mod),
958 Allow(Target::Static),
959 Allow(Target::Struct),
960 Allow(Target::Trait),
961 Allow(Target::TyAlias),
962 Allow(Target::Union),
963 ]);
965 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["DepNode"]);
966 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
967
968 fn extend(
969 cx: &mut AcceptContext<'_, '_>,
970 args: &ArgParser,
971 ) -> impl IntoIterator<Item = Self::Item> {
972 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
973 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
974 }
975 let item = cx.expect_single_element_list(args, cx.attr_span)?;
976 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
977 cx.adcx().expected_identifier(item.span());
978 return None;
979 };
980 Some(ident)
981 }
982}
983
984pub(crate) struct RustcInsignificantDtorParser;
985
986impl NoArgsAttributeParser for RustcInsignificantDtorParser {
987 const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];
988 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
989 Allow(Target::Enum),
990 Allow(Target::Struct),
991 Allow(Target::ForeignTy),
992 ]);
993 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
994 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;
995}
996
997pub(crate) struct RustcEffectiveVisibilityParser;
998
999impl NoArgsAttributeParser for RustcEffectiveVisibilityParser {
1000 const PATH: &[Symbol] = &[sym::rustc_effective_visibility];
1001 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1002 Allow(Target::Use),
1003 Allow(Target::Static),
1004 Allow(Target::Const),
1005 Allow(Target::Fn),
1006 Allow(Target::Closure),
1007 Allow(Target::Mod),
1008 Allow(Target::ForeignMod),
1009 Allow(Target::TyAlias),
1010 Allow(Target::Enum),
1011 Allow(Target::Variant),
1012 Allow(Target::Struct),
1013 Allow(Target::Field),
1014 Allow(Target::Union),
1015 Allow(Target::Trait),
1016 Allow(Target::TraitAlias),
1017 Allow(Target::Impl { of_trait: false }),
1018 Allow(Target::Impl { of_trait: true }),
1019 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
1020 Allow(Target::AssocConst(AssocCtxt::Trait)),
1021 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
1022 Allow(Target::Method(MethodKind::Inherent)),
1023 Allow(Target::Method(MethodKind::Trait { body: false })),
1024 Allow(Target::Method(MethodKind::Trait { body: true })),
1025 Allow(Target::Method(MethodKind::TraitImpl)),
1026 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
1027 Allow(Target::AssocTy(AssocCtxt::Trait)),
1028 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
1029 Allow(Target::ForeignFn),
1030 Allow(Target::ForeignStatic),
1031 Allow(Target::ForeignTy),
1032 Allow(Target::MacroDef),
1033 Allow(Target::PatField),
1034 Allow(Target::Crate),
1035 ]);
1036 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1037 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;
1038}
1039
1040pub(crate) struct RustcDiagnosticItemParser;
1041
1042impl SingleAttributeParser for RustcDiagnosticItemParser {
1043 const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
1044 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1045 Allow(Target::Trait),
1046 Allow(Target::Struct),
1047 Allow(Target::Enum),
1048 Allow(Target::MacroDef),
1049 Allow(Target::TyAlias),
1050 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
1051 Allow(Target::AssocConst(AssocCtxt::Trait)),
1052 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
1053 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
1054 Allow(Target::AssocTy(AssocCtxt::Trait)),
1055 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
1056 Allow(Target::Fn),
1057 Allow(Target::Const),
1058 Allow(Target::Mod),
1059 Allow(Target::Impl { of_trait: false }),
1060 Allow(Target::Method(MethodKind::Inherent)),
1061 Allow(Target::Method(MethodKind::Trait { body: false })),
1062 Allow(Target::Method(MethodKind::Trait { body: true })),
1063 Allow(Target::Method(MethodKind::TraitImpl)),
1064 Allow(Target::Crate),
1065 ]);
1066 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
1067 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!(
1068 rustc_attrs,
1069 "the `rustc_diagnostic_item` attribute allows the compiler to reference types from the standard library for diagnostic purposes"
1070 );
1071
1072 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
1073 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
1074 let value = cx.expect_string_literal(nv)?;
1075 Some(AttributeKind::RustcDiagnosticItem(value))
1076 }
1077}
1078
1079pub(crate) struct RustcDoNotConstCheckParser;
1080
1081impl NoArgsAttributeParser for RustcDoNotConstCheckParser {
1082 const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];
1083 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1084 Allow(Target::Fn),
1085 Allow(Target::Method(MethodKind::Inherent)),
1086 Allow(Target::Method(MethodKind::TraitImpl)),
1087 Allow(Target::Method(MethodKind::Trait { body: false })),
1088 Allow(Target::Method(MethodKind::Trait { body: true })),
1089 ]);
1090 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!(
1091 rustc_attrs,
1092 "the `rustc_do_not_const_check` attribute skips const-check for this function's body"
1093 );
1094 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;
1095}
1096
1097pub(crate) struct RustcNonnullOptimizationGuaranteedParser;
1098
1099impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser {
1100 const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];
1101 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
1102 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!(
1103 rustc_attrs,
1104 "the `rustc_nonnull_optimization_guaranteed` attribute is just used to document guaranteed niche optimizations in the standard library",
1105 "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"
1106 );
1107 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;
1108}
1109
1110pub(crate) struct RustcStrictCoherenceParser;
1111
1112impl NoArgsAttributeParser for RustcStrictCoherenceParser {
1113 const PATH: &[Symbol] = &[sym::rustc_strict_coherence];
1114 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1115 Allow(Target::Trait),
1116 Allow(Target::Struct),
1117 Allow(Target::Enum),
1118 Allow(Target::Union),
1119 Allow(Target::ForeignTy),
1120 ]);
1121 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1122 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;
1123}
1124
1125pub(crate) struct PreludeImportParser;
1126
1127impl NoArgsAttributeParser for PreludeImportParser {
1128 const PATH: &[Symbol] = &[sym::prelude_import];
1129 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]);
1130 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::prelude_import,
gate_check: rustc_feature::Features::prelude_import,
notes: &[],
}unstable!(prelude_import);
1131 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;
1132}
1133
1134pub(crate) struct RustcDocPrimitiveParser;
1135
1136impl SingleAttributeParser for RustcDocPrimitiveParser {
1137 const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
1138 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Const)]);
1139 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["primitive name"]),
docs: None,
}template!(NameValueStr: "primitive name");
1140 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!(
1141 rustc_attrs,
1142 "the `rustc_doc_primitive` attribute is used by the standard library to provide a way to generate documentation for primitive types"
1143 );
1144
1145 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
1146 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
1147 let value_str = cx.expect_string_literal(nv)?;
1148
1149 Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))
1150 }
1151}
1152
1153pub(crate) struct RustcIntrinsicParser;
1154
1155impl NoArgsAttributeParser for RustcIntrinsicParser {
1156 const PATH: &[Symbol] = &[sym::rustc_intrinsic];
1157 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1158 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::intrinsics,
gate_check: rustc_feature::Features::intrinsics,
notes: &[],
}unstable!(intrinsics);
1159 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;
1160}
1161
1162pub(crate) struct RustcIntrinsicConstStableIndirectParser;
1163
1164impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser {
1165 const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
1166 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1167 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1168 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
1169}
1170
1171pub(crate) struct RustcExhaustiveParser;
1172
1173impl NoArgsAttributeParser for RustcExhaustiveParser {
1174 const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];
1175 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Enum)]);
1176 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1177 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively;
1178}
1179
1180pub(crate) struct RustcCanonicalSymbolParser;
1181
1182impl NoArgsAttributeParser for RustcCanonicalSymbolParser {
1183 const PATH: &[Symbol] = &[sym::rustc_canonical_symbol];
1184 const ALLOWED_TARGETS: AllowedTargets<'_> =
1185 AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
1186 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!(
1187 rustc_attrs,
1188 "the `rustc_canonical_symbol` attribute registers a function's symbol to be linted against \
1189 by the `invalid_runtime_symbol_definitions` and `suspicious_runtime_symbol_definitions` \
1190 lints"
1191 );
1192 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCanonicalSymbol;
1193}