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