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