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