1use std::path::PathBuf;23use rustc_ast::{LitIntType, LitKind, MetaItemLit};4use rustc_attr_ir::lang_items::LangItem;5use rustc_attr_ir::target::GenericParamKind;6use rustc_attr_ir::{7 BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,8 DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcMirKind,9};10use rustc_data_structures::fx::FxHashMap;11use rustc_feature::AttributeStability;12use rustc_span::Symbol;1314use super::prelude::*;15use super::util::parse_single_integer;16use crate::diagnostics;17use crate::diagnostics::{18 AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange,19 UnknownExternLangItem, UnknownLangItem,20};2122pub(crate) struct RustcMainParser;2324impl NoArgsAttributeParser for RustcMainParser {25 const PATH: &[Symbol] = &[sym::rustc_main];26 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);27 const STABILITY: AttributeStability = 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}3334pub(crate) struct RustcMustImplementOneOfParser;3536impl 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 = 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 = template!(List: &["function1, function2, ..."]);44 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {45 let list = cx.expect_list(args, cx.attr_span)?;4647 let mut fn_names = ThinVec::new();4849 let inputs: Vec<_> = list.mixed().collect();5051 if inputs.len() < 2 {52 cx.adcx().expected_list_with_num_args_or_more(2, list.span);53 return None;54 }5556 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 };6263 let Some(ident) = meta.ident() else {64 cx.dcx()65 .emit_err(diagnostics::MustBeNameOfAssociatedFunction { span: meta.span() });66 errored = true;67 continue;68 };6970 fn_names.push(ident);71 }72 if errored {73 return None;74 }7576 if cx.target == Target::Trait {77 // Check for duplicates78 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: vec![dup, ident.span],83 });84 }85 }86 }8788 Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names })89 }90}9192pub(crate) struct RustcNeverReturnsNullPtrParser;9394impl 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 = unstable!(rustc_attrs);104105 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr;106}107108pub(crate) struct RustcPanicsWhenZeroParser;109110impl 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 = unstable!(rustc_attrs);117118 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPanicsWhenZero;119}120121pub(crate) struct RustcNoImplicitAutorefsParser;122123impl 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 = unstable!(rustc_attrs);133134 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;135}136137pub(crate) struct RustcLegacyConstGenericsParser;138139impl 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 = template!(List: &["N"]);143 const STABILITY: AttributeStability = unstable!(rustc_attrs);144145 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {146 let meta_items = cx.expect_list(args, cx.attr_span)?;147148 let mut parsed_indexes = ThinVec::new();149 let mut errored = false;150151 for possible_index in meta_items.mixed() {152 if let MetaItemOrLitParser::Lit(MetaItemLit {153 kind: LitKind::Int(index, LitIntType::Unsuffixed),154 ..155 }) = possible_index156 {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 }169170 Some(AttributeKind::RustcLegacyConstGenerics {171 fn_indexes: parsed_indexes,172 attr_span: cx.attr_span,173 })174 }175}176177pub(crate) struct RustcInheritOverflowChecksParser;178179impl 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 = unstable!(rustc_attrs);188 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInheritOverflowChecks;189}190191pub(crate) struct RustcLintOptDenyFieldAccessParser;192193impl 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 = template!(Word);197 const STABILITY: AttributeStability = 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)?;201202 Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message })203 }204}205206pub(crate) struct RustcLintOptTyParser;207208impl 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 = unstable!(rustc_attrs);212 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy;213}214215fn 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)?;221222 let mut cfg = None::<(Symbol, Span)>;223 let mut module = None::<(Symbol, Span)>;224 let mut kind = None::<(Symbol, Span)>;225226 for arg in args.mixed() {227 let Some((ident, arg)) = cx.expect_name_value(arg, arg.span(), None) else {228 continue;229 };230231 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 };247248 let str = cx.expect_string_literal(arg)?;249250 if res.is_some() {251 cx.adcx().duplicate_key(ident.span.to(arg.args_span()), ident.name);252 continue;253 }254255 *res = Some((str, arg.value_span));256 }257258 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 // return None so that an unwrap for the attributes that need it is ok.282 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 };290291 None292 };293294 Some((cfg, module, kind))295}296297#[derive(Default)]298pub(crate) struct RustcCguTestAttributeParser {299 items: ThinVec<(Span, CguFields)>,300}301302impl AttributeParser for RustcCguTestAttributeParser {303 const ATTRIBUTES: AcceptMapping<Self> = &[304 (305 &[sym::rustc_partition_reused],306 template!(List: &[r#"cfg = "...", module = "...""#]),307 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 template!(List: &[r#"cfg = "...", module = "...""#]),317 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 template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]),327 unstable!(rustc_attrs),328 |this, cx, args| {329 this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| {330 // unwrap ok because if not given, we return None in `parse_cgu_fields`.331 (cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() })332 }));333 },334 ),335 ];336337 const ALLOWED_TARGETS: AllowedTargets<'_> =338 AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]);339340 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {341 Some(AttributeKind::RustcCguTestAttr(self.items))342 }343}344345pub(crate) struct RustcDeprecatedSafe2024Parser;346347impl 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 = template!(List: &[r#"audit_that = "...""#]);357 const STABILITY: AttributeStability = unstable!(rustc_attrs);358359 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {360 let single = cx.expect_single_element_list(args, cx.attr_span)?;361362 let (path, arg) = cx.expect_name_value(single, cx.attr_span, None)?;363364 if path.name != sym::audit_that {365 cx.adcx().expected_specific_argument(path.span, &[sym::audit_that]);366 return None;367 };368369 let suggestion = cx.expect_string_literal(arg)?;370371 Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion })372 }373}374375pub(crate) struct RustcConversionSuggestionParser;376377impl 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 = unstable!(rustc_attrs);387 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion;388}389390pub(crate) struct RustcCaptureAnalysisParser;391392impl 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 = unstable!(rustc_attrs);397 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis;398}399400pub(crate) struct RustcNeverTypeOptionsParser;401402impl SingleAttributeParser for RustcNeverTypeOptionsParser {403 const PATH: &[Symbol] = &[sym::rustc_never_type_options];404 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);405 const TEMPLATE: AttributeTemplate = template!(List: &[406 r#"fallback = "unit", "never", "no""#,407 r#"diverging_block_default = "unit", "never""#,408 ]);409 const STABILITY: AttributeStability = unstable!(410 rustc_attrs,411 "`rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization"412 );413414 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {415 let list = cx.expect_list(args, cx.attr_span)?;416417 let mut fallback = None::<Ident>;418 let mut diverging_block_default = None::<Ident>;419420 for arg in list.mixed() {421 let Some((ident, arg)) = cx.expect_name_value(arg, arg.span(), None) else {422 continue;423 };424425 let res = match ident.name {426 sym::fallback => &mut fallback,427 sym::diverging_block_default => &mut diverging_block_default,428 _ => {429 cx.adcx().expected_specific_argument(430 ident.span,431 &[sym::fallback, sym::diverging_block_default],432 );433 continue;434 }435 };436437 let field = cx.expect_string_literal(arg)?;438439 if res.is_some() {440 cx.adcx().duplicate_key(ident.span, ident.name);441 continue;442 }443444 *res = Some(Ident { name: field, span: arg.value_span });445 }446447 let fallback = match fallback {448 None => None,449 Some(Ident { name: sym::unit, .. }) => Some(DivergingFallbackBehavior::ToUnit),450 Some(Ident { name: sym::never, .. }) => Some(DivergingFallbackBehavior::ToNever),451 Some(Ident { name: sym::no, .. }) => Some(DivergingFallbackBehavior::NoFallback),452 Some(Ident { span, .. }) => {453 cx.adcx()454 .expected_specific_argument_strings(span, &[sym::unit, sym::never, sym::no]);455 return None;456 }457 };458459 let diverging_block_default = match diverging_block_default {460 None => None,461 Some(Ident { name: sym::unit, .. }) => Some(DivergingBlockBehavior::Unit),462 Some(Ident { name: sym::never, .. }) => Some(DivergingBlockBehavior::Never),463 Some(Ident { span, .. }) => {464 cx.adcx().expected_specific_argument_strings(span, &[sym::unit, sym::no]);465 return None;466 }467 };468469 Some(AttributeKind::RustcNeverTypeOptions { fallback, diverging_block_default })470 }471}472473pub(crate) struct RustcTrivialFieldReadsParser;474475impl NoArgsAttributeParser for RustcTrivialFieldReadsParser {476 const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads];477 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]);478 const STABILITY: AttributeStability = unstable!(rustc_attrs);479 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads;480}481482pub(crate) struct RustcNoMirInlineParser;483484impl NoArgsAttributeParser for RustcNoMirInlineParser {485 const PATH: &[Symbol] = &[sym::rustc_no_mir_inline];486 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[487 Allow(Target::Fn),488 Allow(Target::Method(MethodKind::Inherent)),489 Allow(Target::Method(MethodKind::Trait { body: false })),490 Allow(Target::Method(MethodKind::Trait { body: true })),491 Allow(Target::Method(MethodKind::TraitImpl)),492 ]);493 const STABILITY: AttributeStability = unstable!(rustc_attrs);494 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline;495}496497pub(crate) struct RustcNoWritableParser;498499impl NoArgsAttributeParser for RustcNoWritableParser {500 const PATH: &[Symbol] = &[sym::rustc_no_writable];501 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error;502 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[503 Allow(Target::Fn),504 Allow(Target::Closure),505 Allow(Target::Method(MethodKind::Inherent)),506 Allow(Target::Method(MethodKind::TraitImpl)),507 Allow(Target::Method(MethodKind::Trait { body: true })),508 ]);509 const STABILITY: AttributeStability = unstable!(rustc_attrs);510 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoWritable;511}512513pub(crate) struct RustcLintQueryInstabilityParser;514515impl NoArgsAttributeParser for RustcLintQueryInstabilityParser {516 const PATH: &[Symbol] = &[sym::rustc_lint_query_instability];517 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[518 Allow(Target::Fn),519 Allow(Target::Method(MethodKind::Inherent)),520 Allow(Target::Method(MethodKind::Trait { body: false })),521 Allow(Target::Method(MethodKind::Trait { body: true })),522 Allow(Target::Method(MethodKind::TraitImpl)),523 ]);524 const STABILITY: AttributeStability = unstable!(rustc_attrs);525 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability;526}527528pub(crate) struct RustcRegionsParser;529530impl NoArgsAttributeParser for RustcRegionsParser {531 const PATH: &[Symbol] = &[sym::rustc_regions];532 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[533 Allow(Target::Fn),534 Allow(Target::Method(MethodKind::Inherent)),535 Allow(Target::Method(MethodKind::Trait { body: false })),536 Allow(Target::Method(MethodKind::Trait { body: true })),537 Allow(Target::Method(MethodKind::TraitImpl)),538 ]);539 const STABILITY: AttributeStability = unstable!(rustc_attrs);540 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions;541}542543pub(crate) struct RustcLintUntrackedQueryInformationParser;544545impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser {546 const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information];547 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[548 Allow(Target::Fn),549 Allow(Target::Method(MethodKind::Inherent)),550 Allow(Target::Method(MethodKind::Trait { body: false })),551 Allow(Target::Method(MethodKind::Trait { body: true })),552 Allow(Target::Method(MethodKind::TraitImpl)),553 ]);554 const STABILITY: AttributeStability = unstable!(rustc_attrs);555 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;556}557558pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;559560impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser {561 const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];562 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);563 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");564 const STABILITY: AttributeStability = unstable!(rustc_attrs);565566 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {567 let nv = cx.expect_name_value(args, cx.attr_span, None)?;568 Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))569 }570}571572pub(crate) struct RustcScalableVectorParser;573574impl SingleAttributeParser for RustcScalableVectorParser {575 const PATH: &[Symbol] = &[sym::rustc_scalable_vector];576 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);577 const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);578 const STABILITY: AttributeStability = unstable!(rustc_attrs);579580 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {581 if args.as_no_args().is_ok() {582 return Some(AttributeKind::RustcScalableVector { element_count: None });583 }584585 let n = parse_single_integer(cx, args)?;586 let Ok(n) = n.try_into() else {587 cx.emit_err(RustcScalableVectorCountOutOfRange { span: cx.attr_span, n });588 return None;589 };590 Some(AttributeKind::RustcScalableVector { element_count: Some(n) })591 }592}593594pub(crate) struct LangParser;595596impl SingleAttributeParser for LangParser {597 const PATH: &[Symbol] = &[sym::lang];598 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::ManuallyChecked;599 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");600 const STABILITY: AttributeStability = unstable!(lang_items);601602 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {603 let nv = cx.expect_name_value(args, cx.attr_span, None)?;604 let name = cx.expect_string_literal(nv)?;605 let Some(lang_item) = LangItem::from_name(name) else {606 cx.emit_err(UnknownLangItem { span: cx.attr_span, name });607 return None;608 };609610 // Only weak lang items may be applied to foreign items,611 // except for `ForeignTy` which can be a normal lang item.612 if [Target::ForeignFn, Target::ForeignStatic, Target::ForeignMod].contains(&cx.target)613 && !lang_item.is_weak()614 {615 cx.emit_err(UnknownExternLangItem { span: cx.attr_span, lang_item: lang_item.name() });616 return None;617 }618619 // Check the target620 let allowed_targets: &[_] = &[Allow(lang_item.target())];621 cx.check_target(&format!(" = \"{name}\""), &AllowedTargets::AllowList(allowed_targets));622623 Some(AttributeKind::Lang(lang_item))624 }625}626627pub(crate) struct RustcHasIncoherentInherentImplsParser;628629impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser {630 const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls];631 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[632 Allow(Target::Trait),633 Allow(Target::Struct),634 Allow(Target::Enum),635 Allow(Target::Union),636 Allow(Target::ForeignTy),637 ]);638 const STABILITY: AttributeStability = unstable!(rustc_attrs);639 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;640}641642pub(crate) struct PanicHandlerParser;643644impl NoArgsAttributeParser for PanicHandlerParser {645 const PATH: &[Symbol] = &[sym::panic_handler];646 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);647 const STABILITY: AttributeStability = AttributeStability::Stable;648 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Lang(LangItem::PanicImpl);649}650651pub(crate) struct RustcNounwindParser;652653impl NoArgsAttributeParser for RustcNounwindParser {654 const PATH: &[Symbol] = &[sym::rustc_nounwind];655 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[656 Allow(Target::Fn),657 Allow(Target::ForeignFn),658 Allow(Target::Method(MethodKind::Inherent)),659 Allow(Target::Method(MethodKind::TraitImpl)),660 Allow(Target::Method(MethodKind::Trait { body: true })),661 ]);662 const STABILITY: AttributeStability = unstable!(rustc_attrs);663 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind;664}665666pub(crate) struct RustcOffloadKernelParser;667668impl NoArgsAttributeParser for RustcOffloadKernelParser {669 const PATH: &[Symbol] = &[sym::rustc_offload_kernel];670 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);671 const STABILITY: AttributeStability = unstable!(rustc_attrs);672 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;673}674675pub(crate) struct RustcMirParser;676677impl CombineAttributeParser for RustcMirParser {678 const PATH: &[Symbol] = &[sym::rustc_mir];679680 type Item = RustcMirKind;681682 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items);683 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[684 Allow(Target::Fn),685 Allow(Target::Method(MethodKind::Inherent)),686 Allow(Target::Method(MethodKind::TraitImpl)),687 Allow(Target::Method(MethodKind::Trait { body: false })),688 Allow(Target::Method(MethodKind::Trait { body: true })),689 ]);690 const TEMPLATE: AttributeTemplate = template!(List: &["arg1, arg2, ..."]);691 const STABILITY: AttributeStability = unstable!(rustc_attrs);692693 fn extend(694 cx: &mut AcceptContext<'_, '_>,695 args: &ArgParser,696 ) -> impl IntoIterator<Item = Self::Item> {697 let Some(list) = cx.expect_list(args, cx.attr_span) else {698 return ThinVec::new();699 };700701 list.mixed()702 .filter_map(|arg| arg.meta_item())703 .filter_map(|mi| {704 if let Some(ident) = mi.ident() {705 match ident.name {706 sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit),707 sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit),708 sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness),709 sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow),710 sym::borrowck_graphviz_postflow => {711 let nv = cx.expect_name_value(712 mi.args(),713 mi.span(),714 Some(sym::borrowck_graphviz_postflow),715 )?;716 let path = cx.expect_string_literal(nv)?;717 let path = PathBuf::from(path.to_string());718 if path.file_name().is_some() {719 Some(RustcMirKind::BorrowckGraphvizPostflow { path })720 } else {721 cx.adcx().expected_filename_literal(nv.value_span);722 None723 }724 }725 sym::borrowck_graphviz_format => {726 let nv = cx.expect_name_value(727 mi.args(),728 mi.span(),729 Some(sym::borrowck_graphviz_format),730 )?;731 let Some(format) = nv.value_as_ident() else {732 cx.adcx().expected_identifier(nv.value_span);733 return None;734 };735 match format.name {736 sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat {737 format: BorrowckGraphvizFormatKind::TwoPhase,738 }),739 _ => {740 cx.adcx()741 .expected_specific_argument(format.span, &[sym::two_phase]);742 None743 }744 }745 }746 _ => None,747 }748 } else {749 None750 }751 })752 .collect()753 }754}755pub(crate) struct RustcNonConstTraitMethodParser;756757impl NoArgsAttributeParser for RustcNonConstTraitMethodParser {758 const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method];759 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[760 Allow(Target::Method(MethodKind::Trait { body: true })),761 Allow(Target::Method(MethodKind::Trait { body: false })),762 ]);763 const STABILITY: AttributeStability = unstable!(764 rustc_attrs,765 "the `rustc_non_const_trait_method` attribute should only be used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const"766 );767 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;768}769770pub(crate) struct RustcCleanParser;771772impl CombineAttributeParser for RustcCleanParser {773 const PATH: &[Symbol] = &[sym::rustc_clean];774775 type Item = RustcCleanAttribute;776777 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items);778 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[779 // tidy-alphabetical-start780 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),781 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),782 Allow(Target::AssocConst(AssocCtxt::Trait)),783 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),784 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),785 Allow(Target::AssocTy(AssocCtxt::Trait)),786 Allow(Target::Const),787 Allow(Target::Enum),788 Allow(Target::Expression),789 Allow(Target::Field),790 Allow(Target::Fn),791 Allow(Target::ForeignMod),792 Allow(Target::Impl { of_trait: false }),793 Allow(Target::Impl { of_trait: true }),794 Allow(Target::Method(MethodKind::Inherent)),795 Allow(Target::Method(MethodKind::Trait { body: false })),796 Allow(Target::Method(MethodKind::Trait { body: true })),797 Allow(Target::Method(MethodKind::TraitImpl)),798 Allow(Target::Mod),799 Allow(Target::Static),800 Allow(Target::Struct),801 Allow(Target::Trait),802 Allow(Target::TyAlias),803 Allow(Target::Union),804 // tidy-alphabetical-end805 ]);806 const STABILITY: AttributeStability = unstable!(rustc_attrs);807 const TEMPLATE: AttributeTemplate =808 template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]);809810 fn extend(811 cx: &mut AcceptContext<'_, '_>,812 args: &ArgParser,813 ) -> impl IntoIterator<Item = Self::Item> {814 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {815 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });816 }817 let list = cx.expect_list(args, cx.attr_span)?;818819 let mut except = None;820 let mut loaded_from_disk = None;821 let mut cfg = None;822823 for item in list.mixed() {824 let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {825 continue;826 };827 let value_span = value.value_span;828 let Some(value) = cx.expect_string_literal(value) else {829 continue;830 };831 match ident.name {832 sym::cfg if cfg.is_some() => {833 cx.adcx().duplicate_key(item.span(), sym::cfg);834 }835 sym::cfg => {836 cfg = Some(value);837 }838 sym::except if except.is_some() => {839 cx.adcx().duplicate_key(item.span(), sym::except);840 }841 sym::except => {842 let entries =843 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();844 except = Some(RustcCleanQueries { entries, span: value_span });845 }846 sym::loaded_from_disk if loaded_from_disk.is_some() => {847 cx.adcx().duplicate_key(item.span(), sym::loaded_from_disk);848 }849 sym::loaded_from_disk => {850 let entries =851 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();852 loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span });853 }854 _ => {855 cx.adcx().expected_specific_argument(856 ident.span,857 &[sym::cfg, sym::except, sym::loaded_from_disk],858 );859 }860 }861 }862 let Some(cfg) = cfg else {863 cx.adcx().expected_specific_argument(list.span, &[sym::cfg]);864 return None;865 };866867 Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk })868 }869}870871pub(crate) struct RustcIfThisChangedParser;872873impl SingleAttributeParser for RustcIfThisChangedParser {874 const PATH: &[Symbol] = &[sym::rustc_if_this_changed];875 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[876 // tidy-alphabetical-start877 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),878 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),879 Allow(Target::AssocConst(AssocCtxt::Trait)),880 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),881 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),882 Allow(Target::AssocTy(AssocCtxt::Trait)),883 Allow(Target::Const),884 Allow(Target::Enum),885 Allow(Target::Expression),886 Allow(Target::Field),887 Allow(Target::Fn),888 Allow(Target::ForeignMod),889 Allow(Target::Impl { of_trait: false }),890 Allow(Target::Impl { of_trait: true }),891 Allow(Target::Method(MethodKind::Inherent)),892 Allow(Target::Method(MethodKind::Trait { body: false })),893 Allow(Target::Method(MethodKind::Trait { body: true })),894 Allow(Target::Method(MethodKind::TraitImpl)),895 Allow(Target::Mod),896 Allow(Target::Static),897 Allow(Target::Struct),898 Allow(Target::Trait),899 Allow(Target::TyAlias),900 Allow(Target::Union),901 // tidy-alphabetical-end902 ]);903 const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]);904 const STABILITY: AttributeStability = unstable!(rustc_attrs);905906 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {907 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {908 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });909 }910 match args {911 ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),912 ArgParser::List(list) => {913 let item = cx.expect_single(list)?;914 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {915 cx.adcx().expected_identifier(item.span());916 return None;917 };918 Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name)))919 }920 ArgParser::NameValue(_) => {921 let inner_span = cx.inner_span;922 cx.adcx().expected_list_or_no_args(inner_span);923 None924 }925 }926 }927}928929pub(crate) struct RustcThenThisWouldNeedParser;930931impl CombineAttributeParser for RustcThenThisWouldNeedParser {932 const PATH: &[Symbol] = &[sym::rustc_then_this_would_need];933 type Item = Ident;934935 const CONVERT: ConvertFn<Self::Item> =936 |items, _span| AttributeKind::RustcThenThisWouldNeed(items);937 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[938 // tidy-alphabetical-start939 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),940 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),941 Allow(Target::AssocConst(AssocCtxt::Trait)),942 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),943 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),944 Allow(Target::AssocTy(AssocCtxt::Trait)),945 Allow(Target::Const),946 Allow(Target::Enum),947 Allow(Target::Expression),948 Allow(Target::Field),949 Allow(Target::Fn),950 Allow(Target::ForeignMod),951 Allow(Target::Impl { of_trait: false }),952 Allow(Target::Impl { of_trait: true }),953 Allow(Target::Method(MethodKind::Inherent)),954 Allow(Target::Method(MethodKind::Trait { body: false })),955 Allow(Target::Method(MethodKind::Trait { body: true })),956 Allow(Target::Method(MethodKind::TraitImpl)),957 Allow(Target::Mod),958 Allow(Target::Static),959 Allow(Target::Struct),960 Allow(Target::Trait),961 Allow(Target::TyAlias),962 Allow(Target::Union),963 // tidy-alphabetical-end964 ]);965 const TEMPLATE: AttributeTemplate = template!(List: &["DepNode"]);966 const STABILITY: AttributeStability = unstable!(rustc_attrs);967968 fn extend(969 cx: &mut AcceptContext<'_, '_>,970 args: &ArgParser,971 ) -> impl IntoIterator<Item = Self::Item> {972 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {973 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });974 }975 let item = cx.expect_single_element_list(args, cx.attr_span)?;976 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {977 cx.adcx().expected_identifier(item.span());978 return None;979 };980 Some(ident)981 }982}983984pub(crate) struct RustcInsignificantDtorParser;985986impl NoArgsAttributeParser for RustcInsignificantDtorParser {987 const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];988 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[989 Allow(Target::Enum),990 Allow(Target::Struct),991 Allow(Target::ForeignTy),992 ]);993 const STABILITY: AttributeStability = unstable!(rustc_attrs);994 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;995}996997pub(crate) struct RustcEffectiveVisibilityParser;998999impl NoArgsAttributeParser for RustcEffectiveVisibilityParser {1000 const PATH: &[Symbol] = &[sym::rustc_effective_visibility];1001 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1002 Allow(Target::Use),1003 Allow(Target::Static),1004 Allow(Target::Const),1005 Allow(Target::Fn),1006 Allow(Target::Closure),1007 Allow(Target::Mod),1008 Allow(Target::ForeignMod),1009 Allow(Target::TyAlias),1010 Allow(Target::Enum),1011 Allow(Target::Variant),1012 Allow(Target::Struct),1013 Allow(Target::Field),1014 Allow(Target::Union),1015 Allow(Target::Trait),1016 Allow(Target::TraitAlias),1017 Allow(Target::Impl { of_trait: false }),1018 Allow(Target::Impl { of_trait: true }),1019 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),1020 Allow(Target::AssocConst(AssocCtxt::Trait)),1021 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),1022 Allow(Target::Method(MethodKind::Inherent)),1023 Allow(Target::Method(MethodKind::Trait { body: false })),1024 Allow(Target::Method(MethodKind::Trait { body: true })),1025 Allow(Target::Method(MethodKind::TraitImpl)),1026 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),1027 Allow(Target::AssocTy(AssocCtxt::Trait)),1028 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),1029 Allow(Target::ForeignFn),1030 Allow(Target::ForeignStatic),1031 Allow(Target::ForeignTy),1032 Allow(Target::MacroDef),1033 Allow(Target::PatField),1034 Allow(Target::Crate),1035 ]);1036 const STABILITY: AttributeStability = unstable!(rustc_attrs);1037 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;1038}10391040pub(crate) struct RustcDiagnosticItemParser;10411042impl SingleAttributeParser for RustcDiagnosticItemParser {1043 const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];1044 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1045 Allow(Target::Trait),1046 Allow(Target::Struct),1047 Allow(Target::Enum),1048 Allow(Target::MacroDef),1049 Allow(Target::TyAlias),1050 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),1051 Allow(Target::AssocConst(AssocCtxt::Trait)),1052 Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),1053 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),1054 Allow(Target::AssocTy(AssocCtxt::Trait)),1055 Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),1056 Allow(Target::Fn),1057 Allow(Target::Const),1058 Allow(Target::Mod),1059 Allow(Target::Impl { of_trait: false }),1060 Allow(Target::Method(MethodKind::Inherent)),1061 Allow(Target::Method(MethodKind::Trait { body: false })),1062 Allow(Target::Method(MethodKind::Trait { body: true })),1063 Allow(Target::Method(MethodKind::TraitImpl)),1064 Allow(Target::Crate),1065 ]);1066 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");1067 const STABILITY: AttributeStability = unstable!(1068 rustc_attrs,1069 "the `rustc_diagnostic_item` attribute allows the compiler to reference types from the standard library for diagnostic purposes"1070 );10711072 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {1073 let nv = cx.expect_name_value(args, cx.attr_span, None)?;1074 let value = cx.expect_string_literal(nv)?;1075 Some(AttributeKind::RustcDiagnosticItem(value))1076 }1077}10781079pub(crate) struct RustcDoNotConstCheckParser;10801081impl NoArgsAttributeParser for RustcDoNotConstCheckParser {1082 const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];1083 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1084 Allow(Target::Fn),1085 Allow(Target::Method(MethodKind::Inherent)),1086 Allow(Target::Method(MethodKind::TraitImpl)),1087 Allow(Target::Method(MethodKind::Trait { body: false })),1088 Allow(Target::Method(MethodKind::Trait { body: true })),1089 ]);1090 const STABILITY: AttributeStability = unstable!(1091 rustc_attrs,1092 "the `rustc_do_not_const_check` attribute skips const-check for this function's body"1093 );1094 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;1095}10961097pub(crate) struct RustcNonnullOptimizationGuaranteedParser;10981099impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser {1100 const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];1101 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);1102 const STABILITY: AttributeStability = unstable!(1103 rustc_attrs,1104 "the `rustc_nonnull_optimization_guaranteed` attribute is just used to document guaranteed niche optimizations in the standard library",1105 "the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized"1106 );1107 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;1108}11091110pub(crate) struct RustcStrictCoherenceParser;11111112impl NoArgsAttributeParser for RustcStrictCoherenceParser {1113 const PATH: &[Symbol] = &[sym::rustc_strict_coherence];1114 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1115 Allow(Target::Trait),1116 Allow(Target::Struct),1117 Allow(Target::Enum),1118 Allow(Target::Union),1119 Allow(Target::ForeignTy),1120 ]);1121 const STABILITY: AttributeStability = unstable!(rustc_attrs);1122 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;1123}11241125pub(crate) struct RustcReservationImplParser;11261127impl SingleAttributeParser for RustcReservationImplParser {1128 const PATH: &[Symbol] = &[sym::rustc_reservation_impl];1129 const ALLOWED_TARGETS: AllowedTargets<'_> =1130 AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]);1131 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message");1132 const STABILITY: AttributeStability = unstable!(rustc_attrs);11331134 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {1135 let nv = cx.expect_name_value(args, cx.attr_span, None)?;1136 let value_str = cx.expect_string_literal(nv)?;11371138 Some(AttributeKind::RustcReservationImpl(value_str))1139 }1140}11411142pub(crate) struct PreludeImportParser;11431144impl NoArgsAttributeParser for PreludeImportParser {1145 const PATH: &[Symbol] = &[sym::prelude_import];1146 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]);1147 const STABILITY: AttributeStability = unstable!(prelude_import);1148 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;1149}11501151pub(crate) struct RustcDocPrimitiveParser;11521153impl SingleAttributeParser for RustcDocPrimitiveParser {1154 const PATH: &[Symbol] = &[sym::rustc_doc_primitive];1155 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Const)]);1156 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name");1157 const STABILITY: AttributeStability = unstable!(1158 rustc_attrs,1159 "the `rustc_doc_primitive` attribute is used by the standard library to provide a way to generate documentation for primitive types"1160 );11611162 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {1163 let nv = cx.expect_name_value(args, cx.attr_span, None)?;1164 let value_str = cx.expect_string_literal(nv)?;11651166 Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))1167 }1168}11691170pub(crate) struct RustcIntrinsicParser;11711172impl NoArgsAttributeParser for RustcIntrinsicParser {1173 const PATH: &[Symbol] = &[sym::rustc_intrinsic];1174 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);1175 const STABILITY: AttributeStability = unstable!(intrinsics);1176 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;1177}11781179pub(crate) struct RustcIntrinsicConstStableIndirectParser;11801181impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser {1182 const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];1183 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);1184 const STABILITY: AttributeStability = unstable!(rustc_attrs);1185 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;1186}11871188pub(crate) struct RustcExhaustiveParser;11891190impl NoArgsAttributeParser for RustcExhaustiveParser {1191 const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];1192 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Enum)]);1193 const STABILITY: AttributeStability = unstable!(rustc_attrs);1194 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively;1195}11961197pub(crate) struct RustcCanonicalSymbolParser;11981199impl NoArgsAttributeParser for RustcCanonicalSymbolParser {1200 const PATH: &[Symbol] = &[sym::rustc_canonical_symbol];1201 const ALLOWED_TARGETS: AllowedTargets<'_> =1202 AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);1203 const STABILITY: AttributeStability = unstable!(1204 rustc_attrs,1205 "the `rustc_canonical_symbol` attribute registers a function's symbol to be linted against \1206 by the `invalid_runtime_symbol_definitions` and `suspicious_runtime_symbol_definitions` \1207 lints"1208 );1209 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCanonicalSymbol;1210}