From 5ed378402ccbaa270dac4fa5285957c841aacc9e Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 4 Apr 2026 14:49:19 +0200 Subject: [PATCH 1/3] Remove AttributeSafety from BUILTIN_ATTRIBUTES --- .../rustc_attr_parsing/src/attributes/cfg.rs | 2 + .../src/attributes/cfg_select.rs | 2 + .../src/attributes/codegen_attrs.rs | 6 + .../src/attributes/link_attrs.rs | 5 + .../rustc_attr_parsing/src/attributes/mod.rs | 20 + compiler/rustc_attr_parsing/src/context.rs | 4 +- compiler/rustc_attr_parsing/src/interface.rs | 35 +- compiler/rustc_attr_parsing/src/lib.rs | 1 + compiler/rustc_attr_parsing/src/safety.rs | 24 +- compiler/rustc_builtin_macros/src/cfg.rs | 4 +- compiler/rustc_expand/src/config.rs | 5 +- compiler/rustc_expand/src/expand.rs | 5 +- compiler/rustc_feature/src/builtin_attrs.rs | 535 ++++-------------- compiler/rustc_feature/src/lib.rs | 2 +- 14 files changed, 204 insertions(+), 446 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 6410d0c0cf702..84c83be8b4a5d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -19,6 +19,7 @@ use rustc_session::parse::{ParseSess, feature_err}; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use thin_vec::ThinVec; +use crate::attributes::AttributeSafety; use crate::context::{AcceptContext, ShouldEmit, Stage}; use crate::parser::{ AllowExprMetavar, ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser, @@ -410,6 +411,7 @@ fn parse_cfg_attr_internal<'a>( attribute.style, AttrPath { segments: attribute.path().into_boxed_slice(), span: attribute.span }, Some(attribute.get_normal_item().unsafety), + AttributeSafety::Normal, ParsedDescription::Attribute, pred_span, lint_node_id, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 4ff224006ca89..918fd0a4582b7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -12,6 +12,7 @@ use rustc_session::Session; use rustc_session::lint::builtin::UNREACHABLE_CFG_SELECT_PREDICATES; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; +use crate::attributes::AttributeSafety; use crate::parser::{AllowExprMetavar, MetaItemOrLitParser}; use crate::{AttributeParser, ParsedDescription, ShouldEmit, errors, parse_cfg_entry}; @@ -105,6 +106,7 @@ pub fn parse_cfg_select( AttrStyle::Inner, AttrPath { segments: vec![sym::cfg_select].into_boxed_slice(), span: cfg_span }, None, + AttributeSafety::Normal, ParsedDescription::Macro, cfg_span, lint_node_id, diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 73b2727fdab0a..53d02d09bb514 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,7 +1,9 @@ use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy}; use rustc_session::parse::feature_err; +use rustc_span::edition::Edition::Edition2024; use super::prelude::*; +use crate::attributes::AttributeSafety; use crate::session_diagnostics::{ NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, @@ -103,6 +105,7 @@ pub(crate) struct ExportNameParser; impl SingleAttributeParser for ExportNameParser { const PATH: &[rustc_span::Symbol] = &[sym::export_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Static), Allow(Target::Fn), @@ -220,6 +223,7 @@ impl AttributeParser for NakedParser { this.span = Some(cx.attr_span); } })]; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -340,6 +344,7 @@ pub(crate) struct NoMangleParser; impl NoArgsAttributeParser for NoMangleParser { const PATH: &[Symbol] = &[sym::no_mangle]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Static), @@ -542,6 +547,7 @@ pub(crate) struct ForceTargetFeatureParser; impl CombineAttributeParser for ForceTargetFeatureParser { type Item = (Symbol, Span); const PATH: &[Symbol] = &[sym::force_target_feature]; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; const CONVERT: ConvertFn = |items, span| AttributeKind::TargetFeature { features: items, attr_span: span, diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 8aa7759daa043..b6ba7f9e21d49 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -5,11 +5,13 @@ use rustc_hir::attrs::*; use rustc_session::Session; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::feature_err; +use rustc_span::edition::Edition::Edition2024; use rustc_span::kw; use rustc_target::spec::{Arch, BinaryFormat}; use super::prelude::*; use super::util::parse_single_integer; +use crate::attributes::AttributeSafety; use crate::attributes::cfg::parse_cfg_entry; use crate::session_diagnostics::{ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, @@ -463,6 +465,7 @@ pub(crate) struct LinkSectionParser; impl SingleAttributeParser for LinkSectionParser { const PATH: &[Symbol] = &[sym::link_section]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Static), Allow(Target::Fn), @@ -508,6 +511,7 @@ pub(crate) struct FfiConstParser; impl NoArgsAttributeParser for FfiConstParser { const PATH: &[Symbol] = &[sym::ffi_const]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst; } @@ -516,6 +520,7 @@ pub(crate) struct FfiPureParser; impl NoArgsAttributeParser for FfiPureParser { const PATH: &[Symbol] = &[sym::ffi_pure]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index d7f64ff2319a9..ad5a541d3a25d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -18,6 +18,7 @@ use std::marker::PhantomData; use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::AttributeKind; +use rustc_span::edition::Edition; use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; @@ -97,6 +98,7 @@ pub(crate) trait AttributeParser: Default + 'static { /// If an attribute has this symbol, the `accept` function will be called on it. const ATTRIBUTES: AcceptMapping; const ALLOWED_TARGETS: AllowedTargets; + const SAFETY: AttributeSafety = AttributeSafety::Normal; /// The parser has gotten a chance to accept the attributes on an item, /// here it can produce an attribute. @@ -127,6 +129,7 @@ pub(crate) trait SingleAttributeParser: 'static { /// Configures what to do when when the same attribute is /// applied more than once on the same syntax node. const ON_DUPLICATE: OnDuplicate; + const SAFETY: AttributeSafety = AttributeSafety::Normal; const ALLOWED_TARGETS: AllowedTargets; @@ -165,6 +168,7 @@ impl, S: Stage> AttributeParser for Single }, )]; const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; + const SAFETY: AttributeSafety = T::SAFETY; fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { Some(self.1?.0) @@ -217,6 +221,18 @@ impl OnDuplicate { } } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum AttributeSafety { + /// Normal attribute that does not need `#[unsafe(...)]` + Normal, + /// Unsafe attribute that requires safety obligations to be discharged. + /// + /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition + /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in + /// earlier editions, but become unsafe in later ones. + Unsafe { unsafe_since: Option }, +} + /// An even simpler version of [`SingleAttributeParser`]: /// now automatically check that there are no arguments provided to the attribute. /// @@ -226,6 +242,7 @@ pub(crate) trait NoArgsAttributeParser: 'static { const PATH: &[Symbol]; const ON_DUPLICATE: OnDuplicate; const ALLOWED_TARGETS: AllowedTargets; + const SAFETY: AttributeSafety = AttributeSafety::Normal; /// Create the [`AttributeKind`] given attribute's [`Span`]. const CREATE: fn(Span) -> AttributeKind; @@ -242,6 +259,7 @@ impl, S: Stage> Default for WithoutArgs { impl, S: Stage> SingleAttributeParser for WithoutArgs { const PATH: &[Symbol] = T::PATH; const ON_DUPLICATE: OnDuplicate = T::ON_DUPLICATE; + const SAFETY: AttributeSafety = T::SAFETY; const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; const TEMPLATE: AttributeTemplate = template!(Word); @@ -271,6 +289,7 @@ pub(crate) trait CombineAttributeParser: 'static { /// For example, individual representations from `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`, /// where `x` is a vec of these individual reprs. const CONVERT: ConvertFn; + const SAFETY: AttributeSafety = AttributeSafety::Normal; const ALLOWED_TARGETS: AllowedTargets; @@ -312,6 +331,7 @@ impl, S: Stage> AttributeParser for Combine) -> Option { if let Some(first_span) = self.first_span { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 51345162ee071..b28971be3cf3e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -59,7 +59,7 @@ use crate::attributes::stability::*; use crate::attributes::test_attrs::*; use crate::attributes::traits::*; use crate::attributes::transparency::*; -use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; +use crate::attributes::{AttributeParser as _, AttributeSafety, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, MetaItemOrLitParser, RefPathParser}; use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions, @@ -76,6 +76,7 @@ pub(super) struct GroupTypeInnerAccept { pub(super) template: AttributeTemplate, pub(super) accept_fn: AcceptFn, pub(super) allowed_targets: AllowedTargets, + pub(super) safety: AttributeSafety, pub(super) finalizer: FinalizeFn, } @@ -126,6 +127,7 @@ macro_rules! attribute_parsers { accept_fn(s, cx, args) }) }), + safety: <$names as crate::attributes::AttributeParser<$stage>>::SAFETY, allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, finalizer: Box::new(|cx| { let state = STATE_OBJECT.take(); diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 68016d81c954c..85e714a1a917c 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -12,6 +12,7 @@ use rustc_session::Session; use rustc_session::lint::LintId; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use crate::attributes::AttributeSafety; use crate::context::{AcceptContext, FinalizeContext, FinalizeFn, SharedContext, Stage}; use crate::early_parsed::{EARLY_PARSED_ATTRIBUTES, EarlyParsedState}; use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser}; @@ -135,6 +136,7 @@ impl<'sess> AttributeParser<'sess, Early> { parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser) -> Option, template: &AttributeTemplate, allow_expr_metavar: AllowExprMetavar, + expected_safety: AttributeSafety, ) -> Option { let ast::AttrKind::Normal(normal_attr) = &attr.kind else { panic!("parse_single called on a doc attr") @@ -157,6 +159,7 @@ impl<'sess> AttributeParser<'sess, Early> { attr.style, path, Some(normal_attr.item.unsafety), + expected_safety, ParsedDescription::Attribute, target_span, target_node_id, @@ -178,6 +181,7 @@ impl<'sess> AttributeParser<'sess, Early> { attr_style: AttrStyle, attr_path: AttrPath, attr_safety: Option, + expected_safety: AttributeSafety, parsed_description: ParsedDescription, target_span: Span, target_node_id: NodeId, @@ -199,7 +203,13 @@ impl<'sess> AttributeParser<'sess, Early> { sess.psess.buffer_lint(lint_id.lint, span, target_node_id, kind) }; if let Some(safety) = attr_safety { - parser.check_attribute_safety(&attr_path, inner_span, safety, &mut emit_lint) + parser.check_attribute_safety( + &attr_path, + inner_span, + safety, + expected_safety, + &mut emit_lint, + ) } let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext { shared: SharedContext { @@ -314,17 +324,18 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { } }; - self.check_attribute_safety( - &attr_path, - lower_span(n.item.span()), - n.item.unsafety, - &mut emit_lint, - ); - let parts = n.item.path.segments.iter().map(|seg| seg.ident.name).collect::>(); if let Some(accept) = S::parsers().accepters.get(parts.as_slice()) { + self.check_attribute_safety( + &attr_path, + lower_span(n.item.span()), + n.item.unsafety, + accept.safety, + &mut emit_lint, + ); + let Some(args) = ArgParser::from_attr_args( args, &parts, @@ -397,6 +408,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { span: attr_span, }; + self.check_attribute_safety( + &attr_path, + lower_span(n.item.span()), + n.item.unsafety, + AttributeSafety::Normal, + &mut emit_lint, + ); + if !matches!(self.stage.should_emit(), ShouldEmit::Nothing) && target == Target::Crate { diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 93eb5a0c3ab73..1b08ed3c49b78 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -106,6 +106,7 @@ mod session_diagnostics; mod target_checking; pub mod validate_attr; +pub use attributes::AttributeSafety; pub use attributes::cfg::{ CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry, }; diff --git a/compiler/rustc_attr_parsing/src/safety.rs b/compiler/rustc_attr_parsing/src/safety.rs index 262c9c7723eeb..26212ee5f4ca2 100644 --- a/compiler/rustc_attr_parsing/src/safety.rs +++ b/compiler/rustc_attr_parsing/src/safety.rs @@ -1,12 +1,12 @@ use rustc_ast::Safety; use rustc_errors::MultiSpan; -use rustc_feature::{AttributeSafety, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir::AttrPath; use rustc_hir::lints::AttributeLintKind; use rustc_session::lint::LintId; use rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE; use rustc_span::Span; +use crate::attributes::AttributeSafety; use crate::context::Stage; use crate::{AttributeParser, ShouldEmit}; @@ -16,28 +16,23 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { attr_path: &AttrPath, attr_span: Span, attr_safety: Safety, + expected_safety: AttributeSafety, emit_lint: &mut impl FnMut(LintId, MultiSpan, AttributeLintKind), ) { if matches!(self.stage.should_emit(), ShouldEmit::Nothing) { return; } - let name = (attr_path.segments.len() == 1).then_some(attr_path.segments[0]); - - // FIXME: We should retrieve this information from the attribute parsers instead of from `BUILTIN_ATTRIBUTE_MAP` - let builtin_attr_info = name.and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)); - let builtin_attr_safety = builtin_attr_info.map(|x| x.safety); - - match (builtin_attr_safety, attr_safety) { + match (expected_safety, attr_safety) { // - Unsafe builtin attribute // - User wrote `#[unsafe(..)]`, which is permitted on any edition - (Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => { + (AttributeSafety::Unsafe { .. }, Safety::Unsafe(..)) => { // OK } // - Unsafe builtin attribute // - User did not write `#[unsafe(..)]` - (Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => { + (AttributeSafety::Unsafe { unsafe_since }, Safety::Default) => { let path_span = attr_path.span; // If the `attr_item`'s span is not from a macro, then just suggest @@ -96,7 +91,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // - Normal builtin attribute // - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes - (None | Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => { + (AttributeSafety::Normal, Safety::Unsafe(unsafe_span)) => { self.stage.emit_err( self.sess, crate::session_diagnostics::InvalidAttrUnsafe { @@ -108,14 +103,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // - Normal builtin attribute // - No explicit `#[unsafe(..)]` written. - (None | Some(AttributeSafety::Normal), Safety::Default) => { + (AttributeSafety::Normal, Safety::Default) => { // OK } - ( - Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None, - Safety::Safe(..), - ) => { + (_, Safety::Safe(..)) => { self.sess.dcx().span_delayed_bug( attr_span, "`check_attribute_safety` does not expect `Safety::Safe` on attributes", diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index c4a458089f2d2..2872cff0fdc7a 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -6,7 +6,8 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrStyle, token}; use rustc_attr_parsing::parser::{AllowExprMetavar, MetaItemOrLitParser}; use rustc_attr_parsing::{ - self as attr, AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry, + self as attr, AttributeParser, AttributeSafety, CFG_TEMPLATE, ParsedDescription, ShouldEmit, + parse_cfg_entry, }; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_hir::attrs::CfgEntry; @@ -53,6 +54,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result StripUnconfigured<'a> { parse_cfg, &CFG_TEMPLATE, AllowExprMetavar::Yes, + AttributeSafety::Normal, ) else { // Cfg attribute was not parsable, give up return EvalConfigResult::True; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9f5a01452fdc3..e915be8fe12bb 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -15,8 +15,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_attr_parsing::parser::AllowExprMetavar; use rustc_attr_parsing::{ - AttributeParser, CFG_TEMPLATE, Early, EvalConfigResult, ShouldEmit, eval_config_entry, - parse_cfg, validate_attr, + AttributeParser, AttributeSafety, CFG_TEMPLATE, Early, EvalConfigResult, ShouldEmit, + eval_config_entry, parse_cfg, validate_attr, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -2331,6 +2331,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { parse_cfg, &CFG_TEMPLATE, AllowExprMetavar::Yes, + AttributeSafety::Normal, ) else { // Cfg attribute was not parsable, give up return EvalConfigResult::True; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 1c1bca0cbc3cf..cf50b9155cc1f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -5,7 +5,6 @@ use std::sync::LazyLock; use AttributeGate::*; use rustc_data_structures::fx::FxHashMap; use rustc_hir::AttrStyle; -use rustc_span::edition::Edition; use rustc_span::{Symbol, sym}; use crate::Features; @@ -67,23 +66,6 @@ pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym)) } -// If you change this, please modify `src/doc/unstable-book` as well. You must -// move that documentation into the relevant place in the other docs, and -// remove the chapter on the flag. - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum AttributeSafety { - /// Normal attribute that does not need `#[unsafe(...)]` - Normal, - - /// Unsafe attribute that requires safety obligations to be discharged. - /// - /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition - /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in - /// earlier editions, but become unsafe in later ones. - Unsafe { unsafe_since: Option }, -} - #[derive(Clone, Debug, Copy)] pub enum AttributeGate { /// A gated attribute which requires a feature gate to be enabled. @@ -205,54 +187,15 @@ macro_rules! template { } macro_rules! ungated { - (unsafe($edition:ident) $attr:ident $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - safety: AttributeSafety::Unsafe { unsafe_since: Some(Edition::$edition) }, - gate: Ungated, - } - }; - (unsafe $attr:ident $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - safety: AttributeSafety::Unsafe { unsafe_since: None }, - gate: Ungated, - } - }; ($attr:ident $(,)?) => { - BuiltinAttribute { name: sym::$attr, safety: AttributeSafety::Normal, gate: Ungated } + BuiltinAttribute { name: sym::$attr, gate: Ungated } }; } macro_rules! gated { - (unsafe $attr:ident, $gate:ident, $message:expr $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - safety: AttributeSafety::Unsafe { unsafe_since: None }, - gate: Gated { - feature: sym::$gate, - message: $message, - check: Features::$gate, - notes: &[], - }, - } - }; - (unsafe $attr:ident, $message:expr $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - safety: AttributeSafety::Unsafe { unsafe_since: None }, - gate: Gated { - feature: sym::$attr, - message: $message, - check: Features::$attr, - notes: &[], - }, - } - }; ($attr:ident, $gate:ident, $message:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, - safety: AttributeSafety::Normal, gate: Gated { feature: sym::$gate, message: $message, @@ -264,7 +207,6 @@ macro_rules! gated { ($attr:ident, $message:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, - safety: AttributeSafety::Normal, gate: Gated { feature: sym::$attr, message: $message, @@ -289,7 +231,6 @@ macro_rules! rustc_attr { ($attr:ident $(, $notes:expr)* $(,)?) => { BuiltinAttribute { name: sym::$attr, - safety: AttributeSafety::Normal, gate: Gated { feature: sym::rustc_attrs, message: "use of an internal attribute", @@ -299,7 +240,7 @@ macro_rules! rustc_attr { stringify!($attr), "]` attribute is an internal implementation detail that will never be stable"), $($notes),* - ] + ] }, } }; @@ -313,7 +254,6 @@ macro_rules! experimental { pub struct BuiltinAttribute { pub name: Symbol, - pub safety: AttributeSafety, pub gate: AttributeGate, } @@ -364,26 +304,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(no_link), ungated!(repr), // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity - gated!(rustc_align, fn_align, experimental!(rustc_align)), - gated!(rustc_align_static, static_align, experimental!(rustc_align_static)), - ungated!( - unsafe(Edition2024) export_name, - ), - ungated!( - unsafe(Edition2024) link_section, - ), - ungated!( - unsafe(Edition2024) no_mangle, - ), - ungated!( - used, - ), - ungated!( - link_ordinal, - ), - ungated!( - unsafe naked, - ), + gated!(rustc_align,fn_align, experimental!(rustc_align)), + gated!(rustc_align_static,static_align, experimental!(rustc_align_static)), + ungated!(export_name), + ungated!(link_section), + ungated!(no_mangle), + ungated!(used), + ungated!(link_ordinal), + ungated!(naked), // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. rustc_attr!( rustc_pass_indirectly_in_non_rustic_abis, @@ -391,65 +319,36 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Limits: - ungated!( - recursion_limit, - ), - ungated!( - type_length_limit, - ), + ungated!(recursion_limit), + ungated!(type_length_limit), gated!( move_size_limit, large_assignments, experimental!(move_size_limit) ), // Entry point: - ungated!( - no_main, - ), + ungated!(no_main), // Modules, prelude, and resolution: - ungated!( - path, - ), - ungated!( - no_std, - ), - ungated!( - no_implicit_prelude, - ), - ungated!( - non_exhaustive, - ), + ungated!(path), + ungated!(no_std), + ungated!(no_implicit_prelude), + ungated!(non_exhaustive), // Runtime - ungated!( - windows_subsystem, - ), - ungated!( // RFC 2070 - panic_handler, + ungated!(windows_subsystem), + ungated!(// RFC 2070 + panic_handler ), - // Code generation: - ungated!( - inline, - ), - ungated!( - cold, - ), - ungated!( - no_builtins, - ), - ungated!( - target_feature, - ), - ungated!( - track_caller, - ), - ungated!( - instruction_set, - ), - gated!( - unsafe force_target_feature, + ungated!(inline), + ungated!(cold), + ungated!(no_builtins), + ungated!(target_feature), + ungated!(track_caller), + ungated!(instruction_set), + gated!( + force_target_feature, effective_target_features, experimental!(force_target_feature) ), gated!( @@ -461,17 +360,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ coverage_attribute, experimental!(coverage) ), - ungated!( - doc, - ), + ungated!(doc), // Debugging - ungated!( - debugger_visualizer, - ), - ungated!( - collapse_debuginfo, - ), + ungated!(debugger_visualizer), + ungated!(collapse_debuginfo), // ========================================================================== // Unstable attributes: @@ -516,12 +409,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!( - unsafe ffi_pure, - experimental!(ffi_pure) + ffi_pure, experimental!(ffi_pure) ), gated!( - unsafe ffi_const, - experimental!(ffi_const) + ffi_const, experimental!(ffi_const) ), gated!( register_tool, @@ -572,16 +463,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== - ungated!( - feature, - ), + ungated!(feature), // DuplicatesOk since it has its own validation - ungated!( - stable, - ), - ungated!( - unstable, - ), + ungated!(stable), + ungated!(unstable), ungated!(unstable_feature_bound), ungated!(unstable_removed), ungated!(rustc_const_unstable), @@ -605,13 +490,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths" ), - rustc_attr!( - rustc_deprecated_safe_2024, - "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", + rustc_attr!(rustc_deprecated_safe_2024,"`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", ), - rustc_attr!( - rustc_pub_transparent, - "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", + rustc_attr!(rustc_pub_transparent,"used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", ), @@ -636,24 +517,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Runtime related: // ========================================================================== - rustc_attr!( - rustc_allocator, - ), - rustc_attr!( - rustc_nounwind, - ), - rustc_attr!( - rustc_reallocator, - ), - rustc_attr!( - rustc_deallocator, - ), - rustc_attr!( - rustc_allocator_zeroed, - ), - rustc_attr!( - rustc_allocator_zeroed_variant, - ), + rustc_attr!(rustc_allocator), + rustc_attr!(rustc_nounwind), + rustc_attr!(rustc_reallocator), + rustc_attr!(rustc_deallocator), + rustc_attr!(rustc_allocator_zeroed), + rustc_attr!(rustc_allocator_zeroed_variant), gated!( default_lib_allocator, allocator_internals, experimental!(default_lib_allocator), @@ -697,14 +566,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Macro related: // ========================================================================== + rustc_attr!(rustc_offload_kernel), rustc_attr!(rustc_builtin_macro), rustc_attr!(rustc_proc_macro_decls), - rustc_attr!( - rustc_macro_transparency, - "used internally for testing macro hygiene", - ), - rustc_attr!(rustc_autodiff), - rustc_attr!(rustc_offload_kernel), + rustc_attr!(rustc_macro_transparency, "used internally for testing macro hygiene"), // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. // The attributes are not gated, to avoid stability errors, but they cannot be used in stable // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they @@ -720,93 +585,52 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_on_unimplemented, "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" ), - rustc_attr!( - rustc_confusables, - ), + rustc_attr!(rustc_confusables), // Enumerates "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!( - rustc_conversion_suggestion, - ), + rustc_attr!(rustc_conversion_suggestion), // Prevents field reads in the marked trait or method to be considered // during dead code analysis. - rustc_attr!( - rustc_trivial_field_reads, - ), + rustc_attr!(rustc_trivial_field_reads), // Used by the `rustc::potential_query_instability` lint to warn methods which // might not be stable during incremental compilation. - rustc_attr!( - rustc_lint_query_instability, - ), + rustc_attr!(rustc_lint_query_instability), // Used by the `rustc::untracked_query_information` lint to warn methods which // might not be stable during incremental compilation. - rustc_attr!( - rustc_lint_untracked_query_information, - ), + rustc_attr!(rustc_lint_untracked_query_information), // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` // types (as well as any others in future). - rustc_attr!( - rustc_lint_opt_ty, - ), + rustc_attr!(rustc_lint_opt_ty), // Used by the `rustc::bad_opt_access` lint on fields // types (as well as any others in future). - rustc_attr!( - rustc_lint_opt_deny_field_access, - ), + rustc_attr!(rustc_lint_opt_deny_field_access), // ========================================================================== // Internal attributes, Const related: // ========================================================================== - rustc_attr!( - rustc_promotable, - ), - rustc_attr!( - rustc_legacy_const_generics, - ), + rustc_attr!(rustc_promotable), + rustc_attr!(rustc_legacy_const_generics), // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. - rustc_attr!( - rustc_do_not_const_check, - "`#[rustc_do_not_const_check]` skips const-check for this function's body", - ), - rustc_attr!( - rustc_const_stable_indirect, - "this is an internal implementation detail", - ), - rustc_attr!( - rustc_intrinsic_const_stable_indirect, - "this is an internal implementation detail", - ), - rustc_attr!( - rustc_allow_const_fn_unstable, - "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" - ), + rustc_attr!(rustc_do_not_const_check, "`#[rustc_do_not_const_check]` skips const-check for this function's body"), + rustc_attr!(rustc_const_stable_indirect, "this is an internal implementation detail"), + rustc_attr!(rustc_intrinsic_const_stable_indirect, "this is an internal implementation detail"), + rustc_attr!(rustc_allow_const_fn_unstable, "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"), // ========================================================================== // Internal attributes, Layout related: // ========================================================================== - rustc_attr!( - rustc_layout_scalar_valid_range_start, - "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ - niche optimizations in the standard library", - ), - rustc_attr!( - rustc_layout_scalar_valid_range_end, - "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ - niche optimizations in the standard library", - ), - rustc_attr!( - rustc_simd_monomorphize_lane_limit, - "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ - for better error messages", - ), - rustc_attr!( - rustc_nonnull_optimization_guaranteed, + rustc_attr!(rustc_layout_scalar_valid_range_start, "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ + niche optimizations in the standard library"), + rustc_attr!(rustc_layout_scalar_valid_range_end, "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ + niche optimizations in the standard library"), + rustc_attr!(rustc_simd_monomorphize_lane_limit, "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ + for better error messages"), + rustc_attr!(rustc_nonnull_optimization_guaranteed, "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", - ), + it is your responsibility to ensure that the attribute is only used on types that are optimized"), // ========================================================================== // Internal attributes, Misc: @@ -815,44 +639,16 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ lang, lang_items, "lang items are subject to change", ), - rustc_attr!( - rustc_as_ptr, - "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations" - ), - rustc_attr!( - rustc_should_not_be_called_on_const_items, - "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts" - ), - rustc_attr!( - rustc_pass_by_value, - "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference" - ), - rustc_attr!( - rustc_never_returns_null_ptr, - "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers" - ), - rustc_attr!( - rustc_no_implicit_autorefs, - "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument" - ), - rustc_attr!( - rustc_coherence_is_core, - "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`" - ), - rustc_attr!( - rustc_coinductive, - "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver" - ), - rustc_attr!( - rustc_allow_incoherent_impl, - "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl" - ), - rustc_attr!( - rustc_preserve_ub_checks, - "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR", - ), - rustc_attr!( - rustc_deny_explicit_impl, + rustc_attr!(rustc_as_ptr, "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations"), + rustc_attr!(rustc_should_not_be_called_on_const_items, "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts"), + rustc_attr!(rustc_pass_by_value, "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference"), + rustc_attr!(rustc_never_returns_null_ptr, "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers"), + rustc_attr!(rustc_no_implicit_autorefs, "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument"), + rustc_attr!(rustc_coherence_is_core, "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`"), + rustc_attr!(rustc_coinductive, "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver"), + rustc_attr!(rustc_allow_incoherent_impl, "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl"), + rustc_attr!(rustc_preserve_ub_checks, "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR"), + rustc_attr!(rustc_deny_explicit_impl, "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls" ), rustc_attr!( @@ -873,7 +669,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ BuiltinAttribute { name: sym::rustc_diagnostic_item, - safety: AttributeSafety::Normal, gate: Gated { feature: sym::rustc_attrs, message: "use of an internal attribute", @@ -897,163 +692,73 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ overflow checking behavior of several functions in the standard library that are inlined \ across crates", ), - rustc_attr!( - rustc_reservation_impl, - "the `#[rustc_reservation_impl]` attribute is internally used \ + rustc_attr!(rustc_reservation_impl,"the `#[rustc_reservation_impl]` attribute is internally used \ for reserving `impl From for T` as part of the effort to stabilize `!`" ), - rustc_attr!( - rustc_test_marker, - "the `#[rustc_test_marker]` attribute is used internally to track tests", - ), - rustc_attr!( - rustc_unsafe_specialization_marker, + rustc_attr!(rustc_test_marker, "the `#[rustc_test_marker]` attribute is used internally to track tests"), + rustc_attr!(rustc_unsafe_specialization_marker, "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" ), rustc_attr!( rustc_specialization_trait, "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), - rustc_attr!( - rustc_main, - "the `#[rustc_main]` attribute is used internally to specify test entry point function", - ), - rustc_attr!( - rustc_skip_during_method_dispatch, - "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ + rustc_attr!(rustc_main,"the `#[rustc_main]` attribute is used internally to specify test entry point function"), + rustc_attr!(rustc_skip_during_method_dispatch, "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is of the following type, for compatibility in \ editions < 2021 (array) or editions < 2024 (boxed_slice)" ), - rustc_attr!( - rustc_must_implement_one_of, - "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ + rustc_attr!(rustc_must_implement_one_of,"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", ), - rustc_attr!( - rustc_doc_primitive, - "the `#[rustc_doc_primitive]` attribute is used by the standard library \ + rustc_attr!(rustc_doc_primitive,"the `#[rustc_doc_primitive]` attribute is used by the standard library \ to provide a way to generate documentation for primitive types", ), gated!( - rustc_intrinsic, intrinsics, - "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items", - ), - rustc_attr!( - rustc_no_mir_inline, - "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" - ), - rustc_attr!( - rustc_force_inline, - "`#[rustc_force_inline]` forces a free function to be inlined" - ), - rustc_attr!( - rustc_scalable_vector, - "`#[rustc_scalable_vector]` defines a scalable vector type" - ), - rustc_attr!( - rustc_must_match_exhaustively, - "enums with `#[rustc_must_match_exhaustively]` must be matched on with a match block that mentions all variants explicitly" + rustc_intrinsic,intrinsics, + "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items"), + rustc_attr!(rustc_no_mir_inline,"`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" ), + rustc_attr!(rustc_force_inline,"`#[rustc_force_inline]` forces a free function to be inlined"), + rustc_attr!(rustc_scalable_vector,"`#[rustc_scalable_vector]` defines a scalable vector type"), // ========================================================================== // Internal attributes, Testing: // ========================================================================== rustc_attr!(TEST, rustc_effective_visibility), - rustc_attr!( - TEST, rustc_dump_inferred_outlives, - ), - rustc_attr!( - TEST, rustc_capture_analysis, - ), - rustc_attr!( - TEST, rustc_insignificant_dtor, - ), - rustc_attr!( - TEST, rustc_no_implicit_bounds, - ), - rustc_attr!( - TEST, rustc_strict_coherence, - ), - rustc_attr!( - TEST, rustc_dump_variances, - ), - rustc_attr!( - TEST, rustc_dump_variances_of_opaques, - ), - rustc_attr!( - TEST, rustc_dump_hidden_type_of_opaques, - ), - rustc_attr!( - TEST, rustc_dump_layout, - ), - rustc_attr!( - TEST, rustc_abi, - ), - rustc_attr!( - TEST, rustc_regions, - ), - rustc_attr!( - TEST, rustc_delayed_bug_from_inside_query, - ), - rustc_attr!( - TEST, rustc_dump_user_args, - ), - rustc_attr!( - TEST, rustc_evaluate_where_clauses, - ), - rustc_attr!( - TEST, rustc_if_this_changed, - ), - rustc_attr!( - TEST, rustc_then_this_would_need, - ), - rustc_attr!( - TEST, rustc_clean, - ), - rustc_attr!( - TEST, rustc_partition_reused, - ), - rustc_attr!( - TEST, rustc_partition_codegened, - ), - rustc_attr!( - TEST, rustc_expected_cgu_reuse, - ), - rustc_attr!( - TEST, rustc_dump_symbol_name, - ), - rustc_attr!( - TEST, rustc_dump_def_path, - ), - rustc_attr!( - TEST, rustc_mir, - ), - gated!( - custom_mir, "the `#[custom_mir]` attribute is just used for the Rust test suite", - ), - rustc_attr!( - TEST, rustc_dump_item_bounds, - ), - rustc_attr!( - TEST, rustc_dump_predicates, - ), - rustc_attr!( - TEST, rustc_dump_def_parents, - ), - rustc_attr!( - TEST, rustc_dump_object_lifetime_defaults, - ), - rustc_attr!( - TEST, rustc_dump_vtable, - ), - rustc_attr!( - TEST, rustc_dummy, - ), - rustc_attr!( - TEST, pattern_complexity_limit, - ), + rustc_attr!(TEST, rustc_dump_inferred_outlives), + rustc_attr!(TEST, rustc_capture_analysis), + rustc_attr!(TEST, rustc_insignificant_dtor), + rustc_attr!(TEST, rustc_no_implicit_bounds), + rustc_attr!(TEST, rustc_strict_coherence), + rustc_attr!(TEST, rustc_dump_variances), + rustc_attr!(TEST, rustc_dump_variances_of_opaques), + //rustc_attr!(TEST, rustc_hidden_type_of_opaques), + //rustc_attr!(TEST, rustc_layout), + rustc_attr!(TEST, rustc_abi), + rustc_attr!(TEST, rustc_regions), + rustc_attr!(TEST, rustc_delayed_bug_from_inside_query), + rustc_attr!(TEST, rustc_dump_user_args), + rustc_attr!(TEST, rustc_evaluate_where_clauses), + rustc_attr!(TEST, rustc_if_this_changed), + rustc_attr!(TEST, rustc_then_this_would_need), + rustc_attr!(TEST, rustc_clean), + rustc_attr!(TEST, rustc_partition_reused), + rustc_attr!(TEST, rustc_partition_codegened), + rustc_attr!(TEST, rustc_expected_cgu_reuse), + //rustc_attr!(TEST, rustc_symbol_name), + //rustc_attr!(TEST, rustc_def_path), + rustc_attr!(TEST, rustc_mir), + gated!(custom_mir,"the `#[custom_mir]` attribute is just used for the Rust test suite"), + rustc_attr!(TEST, rustc_dump_item_bounds), + rustc_attr!(TEST, rustc_dump_predicates), + rustc_attr!(TEST, rustc_dump_def_parents), + rustc_attr!(TEST, rustc_dump_object_lifetime_defaults), + rustc_attr!(TEST, rustc_dump_vtable), + rustc_attr!(TEST, rustc_dummy), + rustc_attr!(TEST, pattern_complexity_limit), ]; pub fn is_builtin_attr_name(name: Symbol) -> bool { diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 34ac6b3f9a7c8..ce3ce6fcccee4 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -129,7 +129,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option Date: Thu, 9 Apr 2026 11:45:38 +0200 Subject: [PATCH 2/3] Add GATED assoc const to attribute parsers --- compiler/rustc_ast_passes/src/feature_gate.rs | 11 +- .../src/attributes/allow_unstable.rs | 9 + .../src/attributes/autodiff.rs | 8 +- .../rustc_attr_parsing/src/attributes/body.rs | 1 + .../rustc_attr_parsing/src/attributes/cfg.rs | 3 +- .../src/attributes/cfg_select.rs | 3 +- .../src/attributes/cfi_encoding.rs | 1 + .../src/attributes/codegen_attrs.rs | 31 +- .../src/attributes/confusables.rs | 1 + .../src/attributes/crate_level.rs | 32 + .../src/attributes/debugger.rs | 1 + .../src/attributes/deprecation.rs | 1 + .../attributes/diagnostic/do_not_recommend.rs | 6 +- .../src/attributes/diagnostic/on_const.rs | 1 + .../src/attributes/diagnostic/on_move.rs | 4 + .../attributes/diagnostic/on_unimplemented.rs | 5 + .../src/attributes/diagnostic/on_unknown.rs | 1 + .../rustc_attr_parsing/src/attributes/doc.rs | 8 +- .../src/attributes/dummy.rs | 6 +- .../src/attributes/inline.rs | 5 + .../src/attributes/instruction_set.rs | 1 + .../src/attributes/link_attrs.rs | 23 +- .../src/attributes/lint_helpers.rs | 19 + .../src/attributes/loop_match.rs | 2 + .../src/attributes/macro_attrs.rs | 7 + .../rustc_attr_parsing/src/attributes/mod.rs | 83 +- .../src/attributes/must_not_suspend.rs | 1 + .../src/attributes/must_use.rs | 2 + .../src/attributes/no_implicit_prelude.rs | 1 + .../src/attributes/no_link.rs | 1 + .../src/attributes/non_exhaustive.rs | 11 +- .../rustc_attr_parsing/src/attributes/path.rs | 1 + .../src/attributes/pin_v2.rs | 10 +- .../src/attributes/prelude.rs | 8 +- .../src/attributes/proc_macro_attrs.rs | 8 +- .../src/attributes/prototype.rs | 10 +- .../rustc_attr_parsing/src/attributes/repr.rs | 12 +- .../src/attributes/rustc_allocator.rs | 6 + .../src/attributes/rustc_dump.rs | 24 +- .../src/attributes/rustc_internal.rs | 158 +++- .../src/attributes/semantics.rs | 4 + .../src/attributes/stability.rs | 26 +- .../src/attributes/test_attrs.rs | 18 + .../src/attributes/traits.rs | 36 + .../src/attributes/transparency.rs | 1 + .../rustc_attr_parsing/src/attributes/util.rs | 9 +- compiler/rustc_attr_parsing/src/context.rs | 8 +- .../rustc_attr_parsing/src/feature_gate.rs | 37 + compiler/rustc_attr_parsing/src/interface.rs | 13 +- compiler/rustc_attr_parsing/src/lib.rs | 3 +- .../rustc_attr_parsing/src/validate_attr.rs | 58 +- compiler/rustc_builtin_macros/src/cfg.rs | 1 + compiler/rustc_expand/src/config.rs | 1 + compiler/rustc_expand/src/expand.rs | 3 +- compiler/rustc_feature/src/builtin_attrs.rs | 836 ++++++------------ compiler/rustc_feature/src/lib.rs | 4 +- compiler/rustc_parse/src/lib.rs | 12 +- .../rustc_parse/src/parser/attr_wrapper.rs | 11 +- compiler/rustc_passes/src/check_attr.rs | 28 +- compiler/rustc_resolve/src/diagnostics.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 5 +- tests/ui/attributes/malformed-attrs.stderr | 18 +- .../malformed-never-type-options.stderr | 4 +- .../ui/consts/gate-do-not-const-check.stderr | 4 +- tests/ui/coroutine/gen_block.e2024.stderr | 30 +- tests/ui/coroutine/gen_block.none.stderr | 40 +- .../feature-gate-allocator_internals.stderr | 4 +- ...-allow-internal-unsafe-nested-macro.stderr | 4 +- ...llow-internal-unstable-nested-macro.stderr | 4 +- ...gate-allow-internal-unstable-struct.stderr | 4 +- ...eature-gate-allow-internal-unstable.stderr | 4 +- .../feature-gate-cfi_encoding.stderr | 4 +- ...-gate-check-nested-macro-invocation.stderr | 4 +- .../feature-gate-compiler-builtins.stderr | 4 +- .../feature-gate-coverage-attribute.stderr | 4 +- .../feature-gate-custom_mir.stderr | 4 +- ...feature-gate-custom_test_frameworks.stderr | 8 +- .../feature-gate-derive-coerce-pointee.stderr | 29 +- ...e-effective-target-features.default.stderr | 4 +- .../feature-gate-export_stable.stderr | 4 +- .../feature-gate-ffi_const.stderr | 4 +- .../feature-gate-ffi_pure.stderr | 4 +- .../feature-gate-fn_align.stderr | 8 +- .../feature-gate-fundamental.stderr | 4 +- .../feature-gate-intrinsics.stderr | 4 +- .../feature-gate-lang-items.stderr | 4 +- .../feature-gate-large-assignments.stderr | 4 +- .../feature-gates/feature-gate-linkage.stderr | 4 +- .../feature-gate-loop-match.stderr | 12 +- .../feature-gate-marker_trait_attr.stderr | 4 +- .../feature-gate-may-dangle.stderr | 4 +- .../feature-gate-needs-allocator.stderr | 4 +- .../feature-gates/feature-gate-no_core.stderr | 4 +- .../feature-gate-optimize_attribute.stderr | 16 +- ...ature-gate-patchable-function-entry.stderr | 4 +- ...ature-gate-pattern-complexity-limit.stderr | 4 +- .../feature-gate-pin_ergonomics.stderr | 4 +- .../feature-gate-prelude_import.stderr | 4 +- .../feature-gate-profiler-runtime.stderr | 4 +- .../feature-gate-register_tool.stderr | 4 +- ...-gate-rustc-allow-const-fn-unstable.stderr | 4 +- .../feature-gate-rustc-attrs-1.stderr | 8 +- .../feature-gate-rustc-attrs.stderr | 4 +- .../feature-gate-sanitize.stderr | 4 +- .../feature-gate-static_align.stderr | 8 +- .../feature-gate-thread_local.stderr | 4 +- .../feature-gated-feature-in-macro-arg.stderr | 4 +- ...43106-gating-of-builtin-attrs-error.stderr | 20 +- tests/ui/force-inlining/gate.stderr | 8 +- .../incorrect-read_via_copy-defn.stderr | 4 +- .../ui/intrinsics/incorrect-transmute.stderr | 4 +- tests/ui/lang-items/issue-83471.stderr | 54 +- tests/ui/linkage-attr/linkage4.stderr | 4 +- .../feature-gate-must_not_suspend.stderr | 4 +- .../feature-gate-on-unimplemented.stderr | 4 +- tests/ui/panic-runtime/needs-gate.stderr | 8 +- .../pattern-matching.normal.stderr | 8 +- .../rustdoc/feature-gate-doc_primitive.stderr | 4 +- tests/ui/thread-local/no-unstable.rs | 7 +- tests/ui/thread-local/no-unstable.stderr | 24 +- .../ui/tool-attributes/diagnostic_item.stderr | 4 +- .../const-traits/partial/attr-gate.stderr | 4 +- .../rustc_must_implement_one_of_gated.stderr | 4 +- 123 files changed, 1199 insertions(+), 930 deletions(-) create mode 100644 compiler/rustc_attr_parsing/src/feature_gate.rs diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 4e3310d3fb097..27ad57485b0c0 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -2,7 +2,7 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{self as ast, AttrVec, GenericBound, NodeId, PatKind, attr, token}; use rustc_attr_parsing::AttributeParser; use rustc_errors::msg; -use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features}; +use rustc_feature::Features; use rustc_hir::Attribute; use rustc_hir::attrs::AttributeKind; use rustc_session::Session; @@ -155,15 +155,6 @@ impl<'a> PostExpansionVisitor<'a> { impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_attribute(&mut self, attr: &ast::Attribute) { - let attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)); - // Check feature gates for built-in attributes. - if let Some(BuiltinAttribute { - gate: AttributeGate::Gated { feature, message, check, notes, .. }, - .. - }) = attr_info - { - gate_alt!(self, check(self.features), *feature, attr.span, *message, *notes); - } // Check unstable flavors of the `#[doc]` attribute. if attr.has_name(sym::doc) { for meta_item_inner in attr.meta_item_list().unwrap_or_default() { diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index c2511ac75d5d2..60333d9ae61e3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -7,6 +7,10 @@ pub(crate) struct AllowInternalUnstableParser; impl CombineAttributeParser for AllowInternalUnstableParser { const PATH: &[Symbol] = &[sym::allow_internal_unstable]; type Item = (Symbol, Span); + const GATED: AttributeGate = gated!( + allow_internal_unstable, + "allow_internal_unstable side-steps feature gating and stability checks" + ); const CONVERT: ConvertFn = |items, span| AttributeKind::AllowInternalUnstable(items, span); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -31,6 +35,7 @@ pub(crate) struct UnstableFeatureBoundParser; impl CombineAttributeParser for UnstableFeatureBoundParser { const PATH: &[rustc_span::Symbol] = &[sym::unstable_feature_bound]; type Item = (Symbol, Span); + const GATED: AttributeGate = Ungated; const CONVERT: ConvertFn = |items, _| AttributeKind::UnstableFeatureBound(items); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), @@ -56,6 +61,10 @@ pub(crate) struct RustcAllowConstFnUnstableParser; impl CombineAttributeParser for RustcAllowConstFnUnstableParser { const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable]; type Item = Symbol; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_allow_const_fn_unstable, + "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" + ); const CONVERT: ConvertFn = |items, first_span| AttributeKind::RustcAllowConstFnUnstable(items, first_span); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs index 31e79e118bfaa..c919739ba8f19 100644 --- a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs +++ b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs @@ -8,17 +8,15 @@ use rustc_hir::{MethodKind, Target}; use rustc_span::{Symbol, sym}; use thin_vec::ThinVec; -use crate::attributes::prelude::Allow; -use crate::attributes::{OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; -use crate::parser::{ArgParser, MetaItemOrLitParser}; -use crate::target_checking::AllowedTargets; +use super::prelude::*; pub(crate) struct RustcAutodiffParser; impl SingleAttributeParser for RustcAutodiffParser { const PATH: &[Symbol] = &[sym::rustc_autodiff]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + // This is actually gated on a std libs feature called `autodiff` + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), diff --git a/compiler/rustc_attr_parsing/src/attributes/body.rs b/compiler/rustc_attr_parsing/src/attributes/body.rs index a1492d7619461..26f4c2d6c731f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/body.rs +++ b/compiler/rustc_attr_parsing/src/attributes/body.rs @@ -7,6 +7,7 @@ pub(crate) struct CoroutineParser; impl NoArgsAttributeParser for CoroutineParser { const PATH: &[Symbol] = &[sym::coroutine]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(coroutines, experimental!(coroutine)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); const CREATE: fn(rustc_span::Span) -> AttributeKind = |span| AttributeKind::Coroutine(span); } diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 84c83be8b4a5d..c7377648c988d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -19,7 +19,7 @@ use rustc_session::parse::{ParseSess, feature_err}; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use thin_vec::ThinVec; -use crate::attributes::AttributeSafety; +use super::prelude::*; use crate::context::{AcceptContext, ShouldEmit, Stage}; use crate::parser::{ AllowExprMetavar, ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser, @@ -412,6 +412,7 @@ fn parse_cfg_attr_internal<'a>( AttrPath { segments: attribute.path().into_boxed_slice(), span: attribute.span }, Some(attribute.get_normal_item().unsafety), AttributeSafety::Normal, + Ungated, ParsedDescription::Attribute, pred_span, lint_node_id, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 918fd0a4582b7..5ab7471f23777 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -12,7 +12,7 @@ use rustc_session::Session; use rustc_session::lint::builtin::UNREACHABLE_CFG_SELECT_PREDICATES; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; -use crate::attributes::AttributeSafety; +use super::prelude::*; use crate::parser::{AllowExprMetavar, MetaItemOrLitParser}; use crate::{AttributeParser, ParsedDescription, ShouldEmit, errors, parse_cfg_entry}; @@ -107,6 +107,7 @@ pub fn parse_cfg_select( AttrPath { segments: vec![sym::cfg_select].into_boxed_slice(), span: cfg_span }, None, AttributeSafety::Normal, + Ungated, ParsedDescription::Macro, cfg_span, lint_node_id, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs index 81d5c8f99f45f..34a0cf5f0c675 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs @@ -2,6 +2,7 @@ use super::prelude::*; pub(crate) struct CfiEncodingParser; impl SingleAttributeParser for CfiEncodingParser { const PATH: &[Symbol] = &[sym::cfi_encoding]; + const GATED: AttributeGate = gated!(cfi_encoding); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Struct), Allow(Target::ForeignTy), diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 53d02d09bb514..5f4ab84093297 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -3,7 +3,6 @@ use rustc_session::parse::feature_err; use rustc_span::edition::Edition::Edition2024; use super::prelude::*; -use crate::attributes::AttributeSafety; use crate::session_diagnostics::{ NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, @@ -12,9 +11,11 @@ use crate::target_checking::Policy::AllowSilent; pub(crate) struct OptimizeParser; +// RFC 2412 impl SingleAttributeParser for OptimizeParser { const PATH: &[Symbol] = &[sym::optimize]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = gated!(optimize_attribute, experimental!(optimize)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Closure), @@ -47,6 +48,7 @@ pub(crate) struct ColdParser; impl NoArgsAttributeParser for ColdParser { const PATH: &[Symbol] = &[sym::cold]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -63,6 +65,7 @@ pub(crate) struct CoverageParser; impl SingleAttributeParser for CoverageParser { const PATH: &[Symbol] = &[sym::coverage]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(coverage_attribute, experimental!(coverage)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Closure), @@ -106,6 +109,7 @@ impl SingleAttributeParser for ExportNameParser { const PATH: &[rustc_span::Symbol] = &[sym::export_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Static), Allow(Target::Fn), @@ -144,6 +148,7 @@ pub(crate) struct RustcObjcClassParser; impl SingleAttributeParser for RustcObjcClassParser { const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_objc_class); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "ClassName"); @@ -176,6 +181,7 @@ pub(crate) struct RustcObjcSelectorParser; impl SingleAttributeParser for RustcObjcSelectorParser { const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_objc_selector); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "methodName"); @@ -210,7 +216,7 @@ pub(crate) struct NakedParser { impl AttributeParser for NakedParser { const ATTRIBUTES: AcceptMapping = - &[(&[sym::naked], template!(Word), |this, cx, args| { + &[(&[sym::naked], template!(Word), Ungated, |this, cx, args| { if let Err(span) = args.no_args() { cx.adcx().expected_no_args(span); return; @@ -324,6 +330,7 @@ pub(crate) struct TrackCallerParser; impl NoArgsAttributeParser for TrackCallerParser { const PATH: &[Symbol] = &[sym::track_caller]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -345,6 +352,7 @@ impl NoArgsAttributeParser for NoMangleParser { const PATH: &[Symbol] = &[sym::no_mangle]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Static), @@ -371,6 +379,7 @@ impl AttributeParser for UsedParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::used], template!(Word, List: &["compiler", "linker"]), + Ungated, |group: &mut Self, cx, args| { let used_by = match args { ArgParser::NoArgs => UsedBy::Default, @@ -515,6 +524,7 @@ pub(crate) struct TargetFeatureParser; impl CombineAttributeParser for TargetFeatureParser { type Item = (Symbol, Span); const PATH: &[Symbol] = &[sym::target_feature]; + const GATED: AttributeGate = Ungated; const CONVERT: ConvertFn = |items, span| AttributeKind::TargetFeature { features: items, attr_span: span, @@ -548,6 +558,8 @@ impl CombineAttributeParser for ForceTargetFeatureParser { type Item = (Symbol, Span); const PATH: &[Symbol] = &[sym::force_target_feature]; const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; + const GATED: AttributeGate = + gated!(effective_target_features, experimental!(force_target_feature)); const CONVERT: ConvertFn = |items, span| AttributeKind::TargetFeature { features: items, attr_span: span, @@ -593,6 +605,8 @@ impl SingleAttributeParser for SanitizeParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(sanitize); + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let Some(list) = args.list() else { let attr_span = cx.attr_span; @@ -696,6 +710,10 @@ pub(crate) struct ThreadLocalParser; impl NoArgsAttributeParser for ThreadLocalParser { const PATH: &[Symbol] = &[sym::thread_local]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = gated!( + thread_local, + "`#[thread_local]` is an experimental feature, and does not currently handle destructors" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ThreadLocal; @@ -707,6 +725,10 @@ impl NoArgsAttributeParser for RustcPassIndirectlyInNonRusticAbisPa const PATH: &[Symbol] = &[sym::rustc_pass_indirectly_in_non_rustic_abis]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const GATED: AttributeGate = gated_rustc_attr!( + rustc_pass_indirectly_in_non_rustic_abis, + "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs" + ); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis; } @@ -715,6 +737,10 @@ pub(crate) struct RustcEiiForeignItemParser; impl NoArgsAttributeParser for RustcEiiForeignItemParser { const PATH: &[Symbol] = &[sym::rustc_eii_foreign_item]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!( + eii_internals, + "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEiiForeignItem; @@ -725,6 +751,7 @@ pub(crate) struct PatchableFunctionEntryParser; impl SingleAttributeParser for PatchableFunctionEntryParser { const PATH: &[Symbol] = &[sym::patchable_function_entry]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(patchable_function_entry); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]); diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index e4634547358c9..8a7afb6673e24 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -11,6 +11,7 @@ impl AttributeParser for ConfusablesParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::rustc_confusables], template!(List: &[r#""name1", "name2", ..."#]), + gated_rustc_attr!(rustc_confusables), |this, cx, args| { let Some(list) = args.list() else { let attr_span = cx.attr_span; diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 774fd0805a7a8..1a2885278be90 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -13,6 +13,7 @@ impl SingleAttributeParser for CrateNameParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const GATED: AttributeGate = Ungated; fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let ArgParser::NameValue(n) = args else { @@ -39,6 +40,8 @@ impl CombineAttributeParser for CrateTypeParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const GATED: AttributeGate = Ungated; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html"); @@ -86,6 +89,7 @@ pub(crate) struct RecursionLimitParser; impl SingleAttributeParser for RecursionLimitParser { const PATH: &[Symbol] = &[sym::recursion_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = Ungated; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); @@ -109,6 +113,7 @@ pub(crate) struct MoveSizeLimitParser; impl SingleAttributeParser for MoveSizeLimitParser { const PATH: &[Symbol] = &[sym::move_size_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(large_assignments, experimental!(move_size_limit)); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); @@ -132,6 +137,7 @@ pub(crate) struct TypeLengthLimitParser; impl SingleAttributeParser for TypeLengthLimitParser { const PATH: &[Symbol] = &[sym::type_length_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = Ungated; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); @@ -155,6 +161,7 @@ pub(crate) struct PatternComplexityLimitParser; impl SingleAttributeParser for PatternComplexityLimitParser { const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, pattern_complexity_limit); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); @@ -178,6 +185,7 @@ pub(crate) struct NoCoreParser; impl NoArgsAttributeParser for NoCoreParser { const PATH: &[Symbol] = &[sym::no_core]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(no_core); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore; } @@ -187,6 +195,7 @@ pub(crate) struct NoStdParser; impl NoArgsAttributeParser for NoStdParser { const PATH: &[Symbol] = &[sym::no_std]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd; } @@ -196,6 +205,7 @@ pub(crate) struct NoMainParser; impl NoArgsAttributeParser for NoMainParser { const PATH: &[Symbol] = &[sym::no_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain; } @@ -205,6 +215,10 @@ pub(crate) struct RustcCoherenceIsCoreParser; impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_coherence_is_core, + "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoherenceIsCore; } @@ -214,6 +228,7 @@ pub(crate) struct WindowsSubsystemParser; impl SingleAttributeParser for WindowsSubsystemParser { const PATH: &[Symbol] = &[sym::windows_subsystem]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"); @@ -248,6 +263,7 @@ pub(crate) struct PanicRuntimeParser; impl NoArgsAttributeParser for PanicRuntimeParser { const PATH: &[Symbol] = &[sym::panic_runtime]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(panic_runtime); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; } @@ -257,6 +273,7 @@ pub(crate) struct NeedsPanicRuntimeParser; impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const PATH: &[Symbol] = &[sym::needs_panic_runtime]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(needs_panic_runtime); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } @@ -266,6 +283,11 @@ pub(crate) struct ProfilerRuntimeParser; impl NoArgsAttributeParser for ProfilerRuntimeParser { const PATH: &[Symbol] = &[sym::profiler_runtime]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!( + profiler_runtime, + "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ + which contains the profiler runtime and will never be stable" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } @@ -275,6 +297,7 @@ pub(crate) struct NoBuiltinsParser; impl NoArgsAttributeParser for NoBuiltinsParser { const PATH: &[Symbol] = &[sym::no_builtins]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; } @@ -284,6 +307,10 @@ pub(crate) struct RustcPreserveUbChecksParser; impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_preserve_ub_checks, + "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } @@ -293,6 +320,8 @@ pub(crate) struct RustcNoImplicitBoundsParser; impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_no_implicit_bounds); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; } @@ -302,6 +331,7 @@ pub(crate) struct DefaultLibAllocatorParser; impl NoArgsAttributeParser for DefaultLibAllocatorParser { const PATH: &[Symbol] = &[sym::default_lib_allocator]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(allocator_internals, experimental!(default_lib_allocator)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; } @@ -311,6 +341,7 @@ pub(crate) struct FeatureParser; impl CombineAttributeParser for FeatureParser { const PATH: &[Symbol] = &[sym::feature]; type Item = Ident; + const GATED: AttributeGate = Ungated; const CONVERT: ConvertFn = AttributeKind::Feature; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]); @@ -359,6 +390,7 @@ pub(crate) struct RegisterToolParser; impl CombineAttributeParser for RegisterToolParser { const PATH: &[Symbol] = &[sym::register_tool]; type Item = Ident; + const GATED: AttributeGate = gated!(register_tool); const CONVERT: ConvertFn = AttributeKind::RegisterTool; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); diff --git a/compiler/rustc_attr_parsing/src/attributes/debugger.rs b/compiler/rustc_attr_parsing/src/attributes/debugger.rs index 65e9b968e946d..e02580eb3c904 100644 --- a/compiler/rustc_attr_parsing/src/attributes/debugger.rs +++ b/compiler/rustc_attr_parsing/src/attributes/debugger.rs @@ -6,6 +6,7 @@ pub(crate) struct DebuggerViualizerParser; impl CombineAttributeParser for DebuggerViualizerParser { const PATH: &[Symbol] = &[sym::debugger_visualizer]; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!( diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 35996904e8c73..98f5a34559beb 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -61,6 +61,7 @@ impl SingleAttributeParser for DeprecatedParser { Allow(Target::Crate), Error(Target::WherePredicate), ]); + const GATED: AttributeGate = Ungated; const TEMPLATE: AttributeTemplate = template!( Word, List: &[r#"since = "version""#, r#"note = "reason""#, r#"since = "version", note = "reason""#], diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs index 9f3d1e29b4dec..68f6b233d4147 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs @@ -4,15 +4,13 @@ use rustc_hir::lints::AttributeLintKind; use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::{Symbol, sym}; -use crate::attributes::{OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; -use crate::parser::ArgParser; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +use super::super::prelude::*; pub(crate) struct DoNotRecommendParser; impl SingleAttributeParser for DoNotRecommendParser { const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: rustc_feature::AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Checked in check_attr. const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */); diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs index 23db854252a37..6ea727fa15377 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs @@ -15,6 +15,7 @@ impl AttributeParser for OnConstParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::diagnostic, sym::on_const], template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), + gated!(diagnostic_on_const, Ignore, experimental!(diagnostic, on_const)), |this, cx, args| { if !cx.features().diagnostic_on_const() { // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs index a79b7d6afbcdc..28e45970020a9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs @@ -57,8 +57,12 @@ impl AttributeParser for OnMoveParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::diagnostic, sym::on_move], template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), + gated!(diagnostic_on_move, Ignore, experimental!(diagnostic, on_move)), |this, cx, args| { this.parse(cx, args, Mode::DiagnosticOnMove); + if cx.do_nothing_due_to_gate { + *this = OnMoveParser::default(); + } }, )]; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs index 12028059b7d40..5724252ce0561 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs @@ -60,6 +60,7 @@ impl AttributeParser for OnUnimplementedParser { ( &[sym::diagnostic, sym::on_unimplemented], template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), + Ungated, |this, cx, args| { this.parse(cx, args, Mode::DiagnosticOnUnimplemented); }, @@ -67,6 +68,10 @@ impl AttributeParser for OnUnimplementedParser { ( &[sym::rustc_on_unimplemented], template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), + gated_rustc_attr!( + rustc_on_unimplemented, + "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" + ), |this, cx, args| { this.parse(cx, args, Mode::RustcOnUnimplemented); }, diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs index dcfba68a4cf8b..5ef57417f2bea 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs @@ -54,6 +54,7 @@ impl AttributeParser for OnUnknownParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::diagnostic, sym::on_unknown], template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), + gated!(diagnostic_on_unknown, Ignore, experimental!(diagnostic, on_unknown)), |this, cx, args| { this.parse(cx, args, Mode::DiagnosticOnUnknown); }, diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 99f856684abd5..eb364fcc6dee8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -1,6 +1,6 @@ use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; use rustc_errors::msg; -use rustc_feature::template; +use rustc_feature::{BUILTIN_ATTRIBUTES, template}; use rustc_hir::Target; use rustc_hir::attrs::{ AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow, @@ -10,8 +10,7 @@ use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, edition, sym}; use thin_vec::ThinVec; -use super::prelude::{ALL_TARGETS, AllowedTargets}; -use super::{AcceptMapping, AttributeParser}; +use super::prelude::*; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser}; use crate::session_diagnostics::{ @@ -39,7 +38,7 @@ fn check_attribute( span: Span, ) -> bool { // FIXME: This should support attributes with namespace like `diagnostic::do_not_recommend`. - if rustc_feature::BUILTIN_ATTRIBUTE_MAP.contains_key(&attribute) { + if BUILTIN_ATTRIBUTES.contains(&attribute) { return true; } cx.emit_err(DocAttributeNotAttribute { span, attribute }); @@ -732,6 +731,7 @@ impl AttributeParser for DocParser { ], NameValueStr: "string" ), + Ungated, |this, cx, args| { this.accept_single_doc_attr(cx, args); }, diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs index ee5c507b62920..c321dbaeef321 100644 --- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs +++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs @@ -2,15 +2,13 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::AttributeKind; use rustc_span::{Symbol, sym}; -use crate::attributes::{OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; -use crate::parser::ArgParser; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +use super::prelude::*; pub(crate) struct RustcDummyParser; impl SingleAttributeParser for RustcDummyParser { const PATH: &[Symbol] = &[sym::rustc_dummy]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dummy); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index e5b2fb130a185..32ebfaf88c047 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -12,6 +12,7 @@ pub(crate) struct InlineParser; impl SingleAttributeParser for InlineParser { const PATH: &[Symbol] = &[sym::inline]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -68,6 +69,10 @@ pub(crate) struct RustcForceInlineParser; impl SingleAttributeParser for RustcForceInlineParser { const PATH: &[Symbol] = &[sym::rustc_force_inline]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_force_inline, + "`#[rustc_force_inline]` forces a free function to be inlined" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), diff --git a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs index 4003aba76af8e..b1ddcee3263c6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs +++ b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs @@ -16,6 +16,7 @@ impl SingleAttributeParser for InstructionSetParser { ]); const TEMPLATE: AttributeTemplate = template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"); const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = Ungated; fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32]; diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index b6ba7f9e21d49..4ae38dbad9526 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -11,7 +11,6 @@ use rustc_target::spec::{Arch, BinaryFormat}; use super::prelude::*; use super::util::parse_single_integer; -use crate::attributes::AttributeSafety; use crate::attributes::cfg::parse_cfg_entry; use crate::session_diagnostics::{ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, @@ -29,6 +28,8 @@ impl SingleAttributeParser for LinkNameParser { Allow(Target::ForeignFn), Allow(Target::ForeignStatic), ]); + const GATED: AttributeGate = Ungated; + const TEMPLATE: AttributeTemplate = template!( NameValueStr: "name", "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute" @@ -63,7 +64,7 @@ impl CombineAttributeParser for LinkParser { r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#, ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` - + const GATED: AttributeGate = Ungated; fn extend( cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser, @@ -473,6 +474,8 @@ impl SingleAttributeParser for LinkSectionParser { Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), ]); + const GATED: AttributeGate = Ungated; + const TEMPLATE: AttributeTemplate = template!( NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute" @@ -503,6 +506,7 @@ pub(crate) struct ExportStableParser; impl NoArgsAttributeParser for ExportStableParser { const PATH: &[Symbol] = &[sym::export_stable]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(export_stable); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable; } @@ -511,6 +515,7 @@ pub(crate) struct FfiConstParser; impl NoArgsAttributeParser for FfiConstParser { const PATH: &[Symbol] = &[sym::ffi_const]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(ffi_const); const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst; @@ -520,6 +525,7 @@ pub(crate) struct FfiPureParser; impl NoArgsAttributeParser for FfiPureParser { const PATH: &[Symbol] = &[sym::ffi_pure]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(ffi_pure); const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; @@ -529,6 +535,7 @@ pub(crate) struct RustcStdInternalSymbolParser; impl NoArgsAttributeParser for RustcStdInternalSymbolParser { const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_std_internal_symbol); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::ForeignFn), @@ -548,6 +555,8 @@ impl SingleAttributeParser for LinkOrdinalParser { Allow(Target::ForeignStatic), Warn(Target::MacroCall), ]); + const GATED: AttributeGate = Ungated; + const TEMPLATE: AttributeTemplate = template!( List: &["ordinal"], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute" @@ -584,6 +593,10 @@ impl SingleAttributeParser for LinkageParser { const PATH: &[Symbol] = &[sym::linkage]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!( + linkage, + "the `linkage` attribute is experimental and not portable across platforms" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -667,6 +680,7 @@ pub(crate) struct NeedsAllocatorParser; impl NoArgsAttributeParser for NeedsAllocatorParser { const PATH: &[Symbol] = &[sym::needs_allocator]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(allocator_internals, experimental!(needs_allocator)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } @@ -676,6 +690,11 @@ pub(crate) struct CompilerBuiltinsParser; impl NoArgsAttributeParser for CompilerBuiltinsParser { const PATH: &[Symbol] = &[sym::compiler_builtins]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!( + compiler_builtins, + "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ + which contains compiler-rt intrinsics and will never be stable" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; } diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 76bddacd20bf4..d30716142dd4e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -4,6 +4,10 @@ pub(crate) struct RustcAsPtrParser; impl NoArgsAttributeParser for RustcAsPtrParser { const PATH: &[Symbol] = &[sym::rustc_as_ptr]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_as_ptr, + "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -18,6 +22,10 @@ pub(crate) struct RustcPubTransparentParser; impl NoArgsAttributeParser for RustcPubTransparentParser { const PATH: &[Symbol] = &[sym::rustc_pub_transparent]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_pub_transparent, + "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), @@ -30,6 +38,11 @@ pub(crate) struct RustcPassByValueParser; impl NoArgsAttributeParser for RustcPassByValueParser { const PATH: &[Symbol] = &[sym::rustc_pass_by_value]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_pass_by_value, + "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), @@ -42,6 +55,11 @@ pub(crate) struct RustcShouldNotBeCalledOnConstItemsParser; impl NoArgsAttributeParser for RustcShouldNotBeCalledOnConstItemsParser { const PATH: &[Symbol] = &[sym::rustc_should_not_be_called_on_const_items]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_should_not_be_called_on_const_items, + "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), @@ -58,5 +76,6 @@ impl NoArgsAttributeParser for AutomaticallyDerivedParser { Error(Target::Crate), Error(Target::WherePredicate), ]); + const GATED: AttributeGate = AttributeGate::Ungated; const CREATE: fn(Span) -> AttributeKind = AttributeKind::AutomaticallyDerived; } diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs index 528090b8673dc..22b26f992265f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -4,6 +4,7 @@ pub(crate) struct LoopMatchParser; impl NoArgsAttributeParser for LoopMatchParser { const PATH: &[Symbol] = &[sym::loop_match]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(loop_match); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::LoopMatch; } @@ -12,6 +13,7 @@ pub(crate) struct ConstContinueParser; impl NoArgsAttributeParser for ConstContinueParser { const PATH: &[Symbol] = &[sym::const_continue]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(loop_match, experimental!(const_continue)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue; } diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index a0ded93180eb0..d9b359dfe3093 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -8,6 +8,7 @@ impl NoArgsAttributeParser for MacroEscapeParser { const PATH: &[Symbol] = &[sym::macro_escape]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS; + const GATED: AttributeGate = AttributeGate::Ungated; const CREATE: fn(Span) -> AttributeKind = AttributeKind::MacroEscape; } @@ -41,6 +42,7 @@ impl AttributeParser for MacroUseParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::macro_use], MACRO_USE_TEMPLATE, + Ungated, |group: &mut Self, cx: &mut AcceptContext<'_, '_, S>, args| { let span = cx.attr_span; group.first_span.get_or_insert(span); @@ -117,6 +119,8 @@ pub(crate) struct AllowInternalUnsafeParser; impl NoArgsAttributeParser for AllowInternalUnsafeParser { const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; + const GATED: AttributeGate = + gated!(allow_internal_unsafe, "allow_internal_unsafe side-steps the unsafe_code lint"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::MacroDef), @@ -137,6 +141,7 @@ impl SingleAttributeParser for MacroExportParser { Error(Target::WherePredicate), Error(Target::Crate), ]); + const GATED: AttributeGate = AttributeGate::Ungated; fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let local_inner_macros = match args { @@ -168,6 +173,7 @@ pub(crate) struct CollapseDebugInfoParser; impl SingleAttributeParser for CollapseDebugInfoParser { const PATH: &[Symbol] = &[sym::collapse_debuginfo]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = Ungated; const TEMPLATE: AttributeTemplate = template!( List: &["no", "external", "yes"], "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute" @@ -204,6 +210,7 @@ pub(crate) struct RustcProcMacroDeclsParser; impl NoArgsAttributeParser for RustcProcMacroDeclsParser { const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(rustc_proc_macro_decls); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls; } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index ad5a541d3a25d..190277a86e6de 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -16,7 +16,7 @@ use std::marker::PhantomData; -use rustc_feature::{AttributeTemplate, template}; +use rustc_feature::{AttributeGate, AttributeTemplate, template}; use rustc_hir::attrs::AttributeKind; use rustc_span::edition::Edition; use rustc_span::{Span, Symbol}; @@ -71,7 +71,8 @@ pub(crate) mod transparency; pub(crate) mod util; type AcceptFn = for<'sess> fn(&mut T, &mut AcceptContext<'_, 'sess, S>, &ArgParser); -type AcceptMapping = &'static [(&'static [Symbol], AttributeTemplate, AcceptFn)]; +type AcceptMapping = + &'static [(&'static [Symbol], AttributeTemplate, AttributeGate, AcceptFn)]; /// An [`AttributeParser`] is a type which searches for syntactic attributes. /// @@ -130,6 +131,7 @@ pub(crate) trait SingleAttributeParser: 'static { /// applied more than once on the same syntax node. const ON_DUPLICATE: OnDuplicate; const SAFETY: AttributeSafety = AttributeSafety::Normal; + const GATED: AttributeGate; const ALLOWED_TARGETS: AllowedTargets; @@ -157,6 +159,7 @@ impl, S: Stage> AttributeParser for Single const ATTRIBUTES: AcceptMapping = &[( T::PATH, >::TEMPLATE, + T::GATED, |group: &mut Single, cx, args| { if let Some(pa) = T::convert(cx, args) { if let Some((_, used)) = group.1 { @@ -243,7 +246,7 @@ pub(crate) trait NoArgsAttributeParser: 'static { const ON_DUPLICATE: OnDuplicate; const ALLOWED_TARGETS: AllowedTargets; const SAFETY: AttributeSafety = AttributeSafety::Normal; - + const GATED: AttributeGate; /// Create the [`AttributeKind`] given attribute's [`Span`]. const CREATE: fn(Span) -> AttributeKind; } @@ -260,6 +263,7 @@ impl, S: Stage> SingleAttributeParser for Without const PATH: &[Symbol] = T::PATH; const ON_DUPLICATE: OnDuplicate = T::ON_DUPLICATE; const SAFETY: AttributeSafety = T::SAFETY; + const GATED: AttributeGate = T::GATED; const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; const TEMPLATE: AttributeTemplate = template!(Word); @@ -290,6 +294,7 @@ pub(crate) trait CombineAttributeParser: 'static { /// where `x` is a vec of these individual reprs. const CONVERT: ConvertFn; const SAFETY: AttributeSafety = AttributeSafety::Normal; + const GATED: AttributeGate; const ALLOWED_TARGETS: AllowedTargets; @@ -325,7 +330,7 @@ impl, S: Stage> Default for Combine { impl, S: Stage> AttributeParser for Combine { const ATTRIBUTES: AcceptMapping = - &[(T::PATH, T::TEMPLATE, |group: &mut Combine, cx, args| { + &[(T::PATH, T::TEMPLATE, T::GATED, |group: &mut Combine, cx, args| { // Keep track of the span of the first attribute, for diagnostics group.first_span.get_or_insert(cx.attr_span); group.items.extend(T::extend(cx, args)) @@ -341,3 +346,73 @@ impl, S: Stage> AttributeParser for Combine { + gated!($attr, Error, experimental!($attr)) + }; + ($attr:ident, $kind:ident) => { + gated!($attr, $kind, experimental!($attr)) + }; + ($gate:ident, $message:expr) => { + gated!($gate, Error, $message) + }; + ($gate:ident, $kind:ident, $message:expr) => { + rustc_feature::AttributeGate::Gated { + gated_attr: rustc_feature::GatedAttribute { + feature: rustc_span::sym::$gate, + message: $message, + check: rustc_feature::Features::$gate, + notes: &[], + }, + kind: rustc_feature::GateKind::$kind, + } + }; +} + +#[macro_export] +macro_rules! experimental { + ($attr:ident) => { + concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") + }; + ($attr_part_1:ident, $attr_part_2:ident) => { + concat!( + "the `#[", + stringify!($attr_part_1), + "::", + stringify!($attr_part_2), + "]` attribute is an experimental feature" + ) + }; +} + +#[macro_export] +macro_rules! gated_rustc_attr { + (TEST, $attr:ident $(,)?) => { + gated_rustc_attr!( + $attr, + concat!( + "the `#[", + stringify!($attr), + "]` attribute is used for rustc unit tests" + ), + ) + }; + ($attr:ident $(, $notes:expr)* $(,)?) => { + rustc_feature::AttributeGate::Gated { + gated_attr: rustc_feature::GatedAttribute { + feature: rustc_span::sym::rustc_attrs, + message: "use of an internal attribute", + check: rustc_feature::Features::rustc_attrs, + notes: &[ + concat!("the `#[", + stringify!($attr), + "]` attribute is an internal implementation detail that will never be stable"), + $($notes),* + ] + }, + kind: rustc_feature::GateKind::Error + } + }; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs index a951518129584..17bd25dc7ca33 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs @@ -12,6 +12,7 @@ impl SingleAttributeParser for MustNotSuspendParser { Allow(Target::Trait), ]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); + const GATED: AttributeGate = gated!(must_not_suspend); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let reason = match args { diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs index 58ad31dd54845..841877d13b104 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -20,6 +20,8 @@ impl SingleAttributeParser for MustUseParser { Allow(Target::Trait), Error(Target::WherePredicate), ]); + const GATED: AttributeGate = AttributeGate::Ungated; + const TEMPLATE: AttributeTemplate = template!( Word, NameValueStr: "reason", "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute" diff --git a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs index 40073ea0f4610..f91834d7fc51b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs @@ -5,6 +5,7 @@ pub(crate) struct NoImplicitPreludeParser; impl NoArgsAttributeParser for NoImplicitPreludeParser { const PATH: &[rustc_span::Symbol] = &[sym::no_implicit_prelude]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoImplicitPrelude; diff --git a/compiler/rustc_attr_parsing/src/attributes/no_link.rs b/compiler/rustc_attr_parsing/src/attributes/no_link.rs index 43cd1c5406e98..7214e18e254b6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/no_link.rs +++ b/compiler/rustc_attr_parsing/src/attributes/no_link.rs @@ -4,6 +4,7 @@ pub(crate) struct NoLinkParser; impl NoArgsAttributeParser for NoLinkParser { const PATH: &[Symbol] = &[sym::no_link]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::ExternCrate), Warn(Target::Field), diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index fc41c073fd27f..45b1127cbd803 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -1,17 +1,10 @@ -use rustc_hir::Target; -use rustc_hir::attrs::AttributeKind; -use rustc_span::{Span, Symbol, sym}; - -use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; -use crate::target_checking::AllowedTargets; -use crate::target_checking::Policy::{Allow, Warn}; - +use super::prelude::*; pub(crate) struct NonExhaustiveParser; impl NoArgsAttributeParser for NonExhaustiveParser { const PATH: &[Symbol] = &[sym::non_exhaustive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Struct), diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs index 08daa4aa5249b..ee48d3d4f2c81 100644 --- a/compiler/rustc_attr_parsing/src/attributes/path.rs +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -5,6 +5,7 @@ pub(crate) struct PathParser; impl SingleAttributeParser for PathParser { const PATH: &[Symbol] = &[sym::path]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Error(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!( diff --git a/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs b/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs index 597a9515b0048..b162a7b8d3b4d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs +++ b/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs @@ -1,17 +1,11 @@ -use rustc_hir::Target; -use rustc_hir::attrs::AttributeKind; -use rustc_span::{Span, Symbol, sym}; - -use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; -use crate::target_checking::AllowedTargets; -use crate::target_checking::Policy::Allow; +use super::prelude::*; pub(crate) struct PinV2Parser; impl NoArgsAttributeParser for PinV2Parser { const PATH: &[Symbol] = &[sym::pin_v2]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: rustc_feature::AttributeGate = gated!(pin_ergonomics, experimental!(pin_v2)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Struct), diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs index 53adf7e31eb73..ee6f204249705 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs @@ -1,6 +1,6 @@ // data structures #[doc(hidden)] -pub(super) use rustc_feature::{AttributeTemplate, template}; +pub(super) use rustc_feature::{AttributeGate, AttributeGate::*, AttributeTemplate, template}; #[doc(hidden)] pub(super) use rustc_hir::attrs::AttributeKind; #[doc(hidden)] @@ -12,8 +12,8 @@ pub(super) use thin_vec::ThinVec; #[doc(hidden)] pub(super) use crate::attributes::{ - AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, NoArgsAttributeParser, - OnDuplicate, SingleAttributeParser, + AcceptMapping, AttributeParser, AttributeSafety, CombineAttributeParser, ConvertFn, + NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; // contexts #[doc(hidden)] @@ -25,3 +25,5 @@ pub(super) use crate::parser::*; pub(super) use crate::target_checking::Policy::{Allow, Error, Warn}; #[doc(hidden)] pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +#[doc(hidden)] +pub(super) use crate::{experimental, gated, gated_rustc_attr}; diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index c5bf8737fffb6..5cef25cfbb855 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -1,3 +1,4 @@ +use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::lints::AttributeLintKind; use rustc_session::lint::builtin::AMBIGUOUS_DERIVE_HELPERS; @@ -11,6 +12,7 @@ impl NoArgsAttributeParser for ProcMacroParser { const PATH: &[Symbol] = &[sym::proc_macro]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; + const GATED: AttributeGate = AttributeGate::Ungated; const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro; } @@ -19,6 +21,7 @@ impl NoArgsAttributeParser for ProcMacroAttributeParser { const PATH: &[Symbol] = &[sym::proc_macro_attribute]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; + const GATED: AttributeGate = AttributeGate::Ungated; const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute; } @@ -27,6 +30,8 @@ impl SingleAttributeParser for ProcMacroDeriveParser { const PATH: &[Symbol] = &[sym::proc_macro_derive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; + const GATED: AttributeGate = AttributeGate::Ungated; + const TEMPLATE: AttributeTemplate = template!( List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" @@ -46,6 +51,7 @@ pub(crate) struct RustcBuiltinMacroParser; impl SingleAttributeParser for RustcBuiltinMacroParser { const PATH: &[Symbol] = &[sym::rustc_builtin_macro]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_builtin_macro); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const TEMPLATE: AttributeTemplate = template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]); @@ -128,7 +134,7 @@ fn parse_derive_like( cx.adcx().expected_identifier(ident.span); return None; } - if rustc_feature::is_builtin_attr_name(ident.name) { + if BUILTIN_ATTRIBUTES.contains(&ident.name) { cx.emit_lint( AMBIGUOUS_DERIVE_HELPERS, AttributeLintKind::AmbiguousDeriveHelpers, diff --git a/compiler/rustc_attr_parsing/src/attributes/prototype.rs b/compiler/rustc_attr_parsing/src/attributes/prototype.rs index e23e2ba633f7f..08fb732d361cf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prototype.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prototype.rs @@ -5,13 +5,8 @@ use rustc_hir::Target; use rustc_hir::attrs::{AttributeKind, MirDialect, MirPhase}; use rustc_span::{Span, Symbol, sym}; -use super::OnDuplicate; -use crate::attributes::SingleAttributeParser; -use crate::context::{AcceptContext, Stage}; -use crate::parser::ArgParser; +use super::prelude::*; use crate::session_diagnostics; -use crate::target_checking::AllowedTargets; -use crate::target_checking::Policy::Allow; pub(crate) struct CustomMirParser; @@ -20,6 +15,9 @@ impl SingleAttributeParser for CustomMirParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = + gated!(custom_mir, "the `#[custom_mir]` attribute is just used for the Rust test suite"); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"dialect = "...", phase = "...""#]); diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 71a41384d213c..3416f8d646ba4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -18,6 +18,7 @@ pub(crate) struct ReprParser; impl CombineAttributeParser for ReprParser { type Item = (ReprAttr, Span); const PATH: &[Symbol] = &[sym::repr]; + const GATED: AttributeGate = Ungated; const CONVERT: ConvertFn = |items, first_span| AttributeKind::Repr { reprs: items, first_span }; // FIXME(jdonszelmann): never used @@ -287,6 +288,7 @@ pub(crate) struct RustcAlignParser(Option<(Align, Span)>); impl RustcAlignParser { const PATH: &[Symbol] = &[sym::rustc_align]; + const GATED: AttributeGate = gated!(fn_align, experimental!(rustc_align)); const TEMPLATE: AttributeTemplate = template!(List: &[""]); fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { @@ -324,7 +326,9 @@ impl RustcAlignParser { } impl AttributeParser for RustcAlignParser { - const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; + const ATTRIBUTES: AcceptMapping = + &[(Self::PATH, Self::TEMPLATE, Self::GATED, Self::parse)]; + // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -345,6 +349,7 @@ pub(crate) struct RustcAlignStaticParser(RustcAlignParser); impl RustcAlignStaticParser { const PATH: &[Symbol] = &[sym::rustc_align_static]; + const GATED: AttributeGate = gated!(static_align, experimental!(rustc_align_static)); const TEMPLATE: AttributeTemplate = RustcAlignParser::TEMPLATE; fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { @@ -353,7 +358,10 @@ impl RustcAlignStaticParser { } impl AttributeParser for RustcAlignStaticParser { - const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; + const ATTRIBUTES: AcceptMapping = + &[(Self::PATH, Self::TEMPLATE, Self::GATED, Self::parse)]; + // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs index cf4f8eab32460..fee4e9be077b4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs @@ -5,6 +5,7 @@ pub(crate) struct RustcAllocatorParser; impl NoArgsAttributeParser for RustcAllocatorParser { const PATH: &[Symbol] = &[sym::rustc_allocator]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_allocator); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocator; @@ -15,6 +16,7 @@ pub(crate) struct RustcAllocatorZeroedParser; impl NoArgsAttributeParser for RustcAllocatorZeroedParser { const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_allocator_zeroed); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocatorZeroed; @@ -25,6 +27,7 @@ pub(crate) struct RustcAllocatorZeroedVariantParser; impl SingleAttributeParser for RustcAllocatorZeroedVariantParser { const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed_variant]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_allocator_zeroed_variant); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function"); @@ -44,6 +47,7 @@ pub(crate) struct RustcDeallocatorParser; impl NoArgsAttributeParser for RustcDeallocatorParser { const PATH: &[Symbol] = &[sym::rustc_deallocator]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_deallocator); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDeallocator; @@ -54,6 +58,8 @@ pub(crate) struct RustcReallocatorParser; impl NoArgsAttributeParser for RustcReallocatorParser { const PATH: &[Symbol] = &[sym::rustc_reallocator]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_reallocator); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcReallocator; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index e1b8b3b29bf00..01a559fee5f79 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -3,14 +3,14 @@ use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use super::prelude::*; -use crate::context::Stage; -use crate::target_checking::AllowedTargets; pub(crate) struct RustcDumpUserArgsParser; impl NoArgsAttributeParser for RustcDumpUserArgsParser { const PATH: &[Symbol] = &[sym::rustc_dump_user_args]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_user_args); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs; } @@ -20,6 +20,7 @@ pub(crate) struct RustcDumpDefParentsParser; impl NoArgsAttributeParser for RustcDumpDefParentsParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_parents]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_def_parents); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; } @@ -28,6 +29,7 @@ pub(crate) struct RustcDumpDefPathParser; impl SingleAttributeParser for RustcDumpDefPathParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_path]; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_def_path); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::TraitImpl)), @@ -53,6 +55,7 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_hidden_type_of_opaques); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; } @@ -62,6 +65,8 @@ pub(crate) struct RustcDumpInferredOutlivesParser; impl NoArgsAttributeParser for RustcDumpInferredOutlivesParser { const PATH: &[Symbol] = &[sym::rustc_dump_inferred_outlives]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_inferred_outlives); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), @@ -76,6 +81,8 @@ pub(crate) struct RustcDumpItemBoundsParser; impl NoArgsAttributeParser for RustcDumpItemBoundsParser { const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_item_bounds); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; } @@ -84,6 +91,7 @@ pub(crate) struct RustcDumpLayoutParser; impl CombineAttributeParser for RustcDumpLayoutParser { const PATH: &[Symbol] = &[sym::rustc_dump_layout]; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_layout); type Item = RustcDumpLayoutKind; @@ -149,6 +157,8 @@ pub(crate) struct RustcDumpObjectLifetimeDefaultsParser; impl NoArgsAttributeParser for RustcDumpObjectLifetimeDefaultsParser { const PATH: &[Symbol] = &[sym::rustc_dump_object_lifetime_defaults]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_object_lifetime_defaults); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::AssocConst), Allow(Target::AssocTy), @@ -176,6 +186,8 @@ pub(crate) struct RustcDumpPredicatesParser; impl NoArgsAttributeParser for RustcDumpPredicatesParser { const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_predicates); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::AssocConst), Allow(Target::AssocTy), @@ -203,6 +215,8 @@ pub(crate) struct RustcDumpSymbolNameParser; impl SingleAttributeParser for RustcDumpSymbolNameParser { const PATH: &[Symbol] = &[sym::rustc_dump_symbol_name]; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_symbol_name); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::TraitImpl)), @@ -228,6 +242,8 @@ pub(crate) struct RustcDumpVariancesParser; impl NoArgsAttributeParser for RustcDumpVariancesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_variances); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Fn), @@ -246,6 +262,8 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_variances_of_opaques); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; } @@ -255,6 +273,8 @@ pub(crate) struct RustcDumpVtableParser; impl NoArgsAttributeParser for RustcDumpVtableParser { const PATH: &[Symbol] = &[sym::rustc_dump_vtable]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_dump_vtable); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Impl { of_trait: true }), Allow(Target::TyAlias), diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 15bcffe529a0c..8758633fde7ff 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use rustc_ast::{LitIntType, LitKind, MetaItemLit}; +use rustc_feature::GatedAttribute; use rustc_hir::LangItem; use rustc_hir::attrs::{ BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior, @@ -20,6 +21,10 @@ pub(crate) struct RustcMainParser; impl NoArgsAttributeParser for RustcMainParser { const PATH: &[Symbol] = &[sym::rustc_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_main, + "the `#[rustc_main]` attribute is used internally to specify test entry point function" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain; } @@ -29,6 +34,12 @@ pub(crate) struct RustcMustImplementOneOfParser; impl SingleAttributeParser for RustcMustImplementOneOfParser { const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_must_implement_one_of, + "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", + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { @@ -75,6 +86,10 @@ pub(crate) struct RustcNeverReturnsNullPtrParser; impl NoArgsAttributeParser for RustcNeverReturnsNullPtrParser { const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_never_returns_null_ptr, + "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -89,6 +104,10 @@ pub(crate) struct RustcNoImplicitAutorefsParser; impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_no_implicit_autorefs, + "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -105,6 +124,7 @@ pub(crate) struct RustcLayoutScalarValidRangeStartParser; impl SingleAttributeParser for RustcLayoutScalarValidRangeStartParser { const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_layout_scalar_valid_range_start); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(List: &["start"]); @@ -119,6 +139,12 @@ pub(crate) struct RustcLayoutScalarValidRangeEndParser; impl SingleAttributeParser for RustcLayoutScalarValidRangeEndParser { const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_layout_scalar_valid_range_start, + "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ + niche optimizations in the standard library" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(List: &["end"]); @@ -133,6 +159,7 @@ pub(crate) struct RustcLegacyConstGenericsParser; impl SingleAttributeParser for RustcLegacyConstGenericsParser { const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_legacy_const_generics); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(List: &["N"]); @@ -177,6 +204,12 @@ pub(crate) struct RustcInheritOverflowChecksParser; impl NoArgsAttributeParser for RustcInheritOverflowChecksParser { const PATH: &[Symbol] = &[sym::rustc_inherit_overflow_checks]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_inherit_overflow_checks, + "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ + overflow checking behavior of several functions in the standard library that are inlined \ + across crates" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -191,6 +224,8 @@ pub(crate) struct RustcLintOptDenyFieldAccessParser; impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_lint_opt_deny_field_access); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]); const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { @@ -207,10 +242,13 @@ impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { } pub(crate) struct RustcLintOptTyParser; +// Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` +// types (as well as any others in future). impl NoArgsAttributeParser for RustcLintOptTyParser { const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_lint_opt_ty); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy; } @@ -320,6 +358,7 @@ impl AttributeParser for RustcCguTestAttributeParser { ( &[sym::rustc_partition_reused], template!(List: &[r#"cfg = "...", module = "...""#]), + gated_rustc_attr!(TEST, rustc_partition_reused), |this, cx, args| { this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { (cx.attr_span, CguFields::PartitionReused { cfg, module }) @@ -329,6 +368,7 @@ impl AttributeParser for RustcCguTestAttributeParser { ( &[sym::rustc_partition_codegened], template!(List: &[r#"cfg = "...", module = "...""#]), + gated_rustc_attr!(TEST, rustc_partition_codegened), |this, cx, args| { this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { (cx.attr_span, CguFields::PartitionCodegened { cfg, module }) @@ -338,6 +378,7 @@ impl AttributeParser for RustcCguTestAttributeParser { ( &[sym::rustc_expected_cgu_reuse], template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]), + gated_rustc_attr!(TEST, rustc_expected_cgu_reuse), |this, cx, args| { this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| { // unwrap ok because if not given, we return None in `parse_cgu_fields`. @@ -360,6 +401,10 @@ pub(crate) struct RustcDeprecatedSafe2024Parser; impl SingleAttributeParser for RustcDeprecatedSafe2024Parser { const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_deprecated_safe_2024, + "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -401,6 +446,8 @@ pub(crate) struct RustcConversionSuggestionParser; impl NoArgsAttributeParser for RustcConversionSuggestionParser { const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_conversion_suggestion); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -416,6 +463,7 @@ pub(crate) struct RustcCaptureAnalysisParser; impl NoArgsAttributeParser for RustcCaptureAnalysisParser { const PATH: &[Symbol] = &[sym::rustc_capture_analysis]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_capture_analysis); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis; } @@ -425,6 +473,11 @@ pub(crate) struct RustcNeverTypeOptionsParser; impl SingleAttributeParser for RustcNeverTypeOptionsParser { const PATH: &[Symbol] = &[sym::rustc_never_type_options]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_never_type_options, + "`rustc_never_type_options` is used to experiment with never type fallback and work on \ + never type stabilization" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"fallback = "unit", "never", "no""#, @@ -508,6 +561,8 @@ pub(crate) struct RustcTrivialFieldReadsParser; impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_trivial_field_reads); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; } @@ -517,6 +572,10 @@ pub(crate) struct RustcNoMirInlineParser; impl NoArgsAttributeParser for RustcNoMirInlineParser { const PATH: &[Symbol] = &[sym::rustc_no_mir_inline]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_no_mir_inline, + "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -528,10 +587,13 @@ impl NoArgsAttributeParser for RustcNoMirInlineParser { } pub(crate) struct RustcLintQueryInstabilityParser; - +// Used by the `rustc::potential_query_instability` lint to warn methods which +// might not be stable during incremental compilation. impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { const PATH: &[Symbol] = &[sym::rustc_lint_query_instability]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_lint_query_instability); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -547,6 +609,7 @@ pub(crate) struct RustcRegionsParser; impl NoArgsAttributeParser for RustcRegionsParser { const PATH: &[Symbol] = &[sym::rustc_regions]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_regions); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -559,10 +622,12 @@ impl NoArgsAttributeParser for RustcRegionsParser { } pub(crate) struct RustcLintUntrackedQueryInformationParser; - +// Used by the `rustc::untracked_query_information` lint to warn methods which +// might not be stable during incremental compilation. impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser { const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_lint_untracked_query_information); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -579,6 +644,11 @@ pub(crate) struct RustcSimdMonomorphizeLaneLimitParser; impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser { const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_simd_monomorphize_lane_limit, + "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ + for better error messages" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); @@ -597,6 +667,10 @@ pub(crate) struct RustcScalableVectorParser; impl SingleAttributeParser for RustcScalableVectorParser { const PATH: &[Symbol] = &[sym::rustc_scalable_vector]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_scalable_vector, + "`#[rustc_scalable_vector]` defines a scalable vector type" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); @@ -622,6 +696,7 @@ pub(crate) struct LangParser; impl SingleAttributeParser for LangParser { const PATH: &[Symbol] = &[sym::lang]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(lang_items, "lang items are subject to change"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); @@ -648,6 +723,11 @@ pub(crate) struct RustcHasIncoherentInherentImplsParser; impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser { const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_has_incoherent_inherent_impls, + "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ + the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Trait), Allow(Target::Struct), @@ -659,10 +739,11 @@ impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParse } pub(crate) struct PanicHandlerParser; - +// RFC 2070 impl NoArgsAttributeParser for PanicHandlerParser { const PATH: &[Symbol] = &[sym::panic_handler]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::Lang(LangItem::PanicImpl, span); } @@ -672,6 +753,7 @@ pub(crate) struct RustcNounwindParser; impl NoArgsAttributeParser for RustcNounwindParser { const PATH: &[Symbol] = &[sym::rustc_nounwind]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_nounwind); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::ForeignFn), @@ -687,6 +769,7 @@ pub(crate) struct RustcOffloadKernelParser; impl NoArgsAttributeParser for RustcOffloadKernelParser { const PATH: &[Symbol] = &[sym::rustc_offload_kernel]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(rustc_offload_kernel); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel; } @@ -698,6 +781,8 @@ impl CombineAttributeParser for RustcMirParser { type Item = RustcMirKind; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_mir); + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcMir(items); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -786,6 +871,11 @@ pub(crate) struct RustcNonConstTraitMethodParser; impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_non_const_trait_method, + "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ + as non-const to allow large traits an easier transition to const" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -800,6 +890,8 @@ impl CombineAttributeParser for RustcCleanParser { type Item = RustcCleanAttribute; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_clean); + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcClean(items); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -906,6 +998,8 @@ impl SingleAttributeParser for RustcIfThisChangedParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_if_this_changed); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ // tidy-alphabetical-start Allow(Target::AssocConst), @@ -966,6 +1060,8 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { const PATH: &[Symbol] = &[sym::rustc_then_this_would_need]; type Item = Ident; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_then_this_would_need); + const CONVERT: ConvertFn = |items, span| AttributeKind::RustcThenThisWouldNeed(span, items); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -1016,6 +1112,8 @@ pub(crate) struct RustcInsignificantDtorParser; impl NoArgsAttributeParser for RustcInsignificantDtorParser { const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_insignificant_dtor); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Struct), @@ -1029,6 +1127,8 @@ pub(crate) struct RustcEffectiveVisibilityParser; impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { const PATH: &[Symbol] = &[sym::rustc_effective_visibility]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_effective_visibility); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Use), Allow(Target::Static), @@ -1068,6 +1168,18 @@ pub(crate) struct RustcDiagnosticItemParser; impl SingleAttributeParser for RustcDiagnosticItemParser { const PATH: &[Symbol] = &[sym::rustc_diagnostic_item]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = Gated { + gated_attr: GatedAttribute { + feature: sym::rustc_attrs, + message: "use of an internal attribute", + check: rustc_feature::Features::rustc_attrs, + notes: &[ + "the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \ + from the standard library for diagnostic purposes", + ], + }, + kind: rustc_feature::GateKind::Error, + }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Trait), Allow(Target::Struct), @@ -1107,6 +1219,11 @@ pub(crate) struct RustcDoNotConstCheckParser; impl NoArgsAttributeParser for RustcDoNotConstCheckParser { const PATH: &[Symbol] = &[sym::rustc_do_not_const_check]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_do_not_const_check, + "`#[rustc_do_not_const_check]` skips const-check for this function's body" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -1122,6 +1239,14 @@ pub(crate) struct RustcNonnullOptimizationGuaranteedParser; impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser { const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_nonnull_optimization_guaranteed, + "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" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed; } @@ -1131,6 +1256,8 @@ pub(crate) struct RustcStrictCoherenceParser; impl NoArgsAttributeParser for RustcStrictCoherenceParser { const PATH: &[Symbol] = &[sym::rustc_strict_coherence]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_strict_coherence); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Trait), Allow(Target::Struct), @@ -1146,6 +1273,11 @@ pub(crate) struct RustcReservationImplParser; impl SingleAttributeParser for RustcReservationImplParser { const PATH: &[Symbol] = &[sym::rustc_reservation_impl]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_reservation_impl, + "the `#[rustc_reservation_impl]` attribute is internally used \ + for reserving `impl From for T` as part of the effort to stabilize `!`" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]); @@ -1168,10 +1300,13 @@ impl SingleAttributeParser for RustcReservationImplParser { } pub(crate) struct PreludeImportParser; +// Used in resolve: impl NoArgsAttributeParser for PreludeImportParser { const PATH: &[Symbol] = &[sym::prelude_import]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = + gated!(prelude_import, "`#[prelude_import]` is for use by rustc only"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport; } @@ -1181,6 +1316,11 @@ pub(crate) struct RustcDocPrimitiveParser; impl SingleAttributeParser for RustcDocPrimitiveParser { const PATH: &[Symbol] = &[sym::rustc_doc_primitive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_doc_primitive, + "the `#[rustc_doc_primitive]` attribute is used by the standard library \ + to provide a way to generate documentation for primitive types", + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name"); @@ -1205,6 +1345,10 @@ pub(crate) struct RustcIntrinsicParser; impl NoArgsAttributeParser for RustcIntrinsicParser { const PATH: &[Symbol] = &[sym::rustc_intrinsic]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!( + intrinsics, + "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic; } @@ -1214,6 +1358,10 @@ pub(crate) struct RustcIntrinsicConstStableIndirectParser; impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser { const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_intrinsic_const_stable_indirect, + "this is an internal implementation detail" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect; } @@ -1223,6 +1371,10 @@ pub(crate) struct RustcExhaustiveParser; impl NoArgsAttributeParser for RustcExhaustiveParser { const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_must_match_exhaustively, + "enums with `#[rustc_must_match_exhaustively]` must be matched on with a match block that mentions all variants explicitly" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Enum)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively; } diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index d7f624832971f..5df2b3c8332ea 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -4,6 +4,10 @@ pub(crate) struct MayDangleParser; impl NoArgsAttributeParser for MayDangleParser { const PATH: &[Symbol] = &[sym::may_dangle]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!( + dropck_eyepatch, + "`may_dangle` has unstable semantics and may be removed in the future" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 0559469bc3691..65fed922183b8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -76,6 +76,7 @@ impl AttributeParser for StabilityParser { ( &[sym::stable], template!(List: &[r#"feature = "name", since = "version""#]), + Ungated, |this, cx, args| { reject_outside_std!(cx); if !this.check_duplicate(cx) @@ -88,6 +89,7 @@ impl AttributeParser for StabilityParser { ( &[sym::unstable], template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), + Ungated, |this, cx, args| { reject_outside_std!(cx); if !this.check_duplicate(cx) @@ -100,6 +102,11 @@ impl AttributeParser for StabilityParser { ( &[sym::rustc_allowed_through_unstable_modules], template!(NameValueStr: "deprecation message"), + gated_rustc_attr!( + rustc_allowed_through_unstable_modules, + "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ + through unstable paths" + ), |this, cx, args| { reject_outside_std!(cx); let Some(nv) = args.name_value() else { @@ -161,6 +168,7 @@ impl AttributeParser for BodyStabilityParser { const ATTRIBUTES: AcceptMapping = &[( &[sym::rustc_default_body_unstable], template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), + Ungated, |this, cx, args| { reject_outside_std!(cx); if this.stability.is_some() { @@ -184,6 +192,8 @@ pub(crate) struct RustcConstStableIndirectParser; impl NoArgsAttributeParser for RustcConstStableIndirectParser { const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; + const GATED: AttributeGate = + gated_rustc_attr!(rustc_const_stable_indirect, "this is an internal implementation detail"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -214,6 +224,7 @@ impl AttributeParser for ConstStabilityParser { ( &[sym::rustc_const_stable], template!(List: &[r#"feature = "name""#]), + Ungated, |this, cx, args| { reject_outside_std!(cx); @@ -230,6 +241,7 @@ impl AttributeParser for ConstStabilityParser { ( &[sym::rustc_const_unstable], template!(List: &[r#"feature = "name""#]), + Ungated, |this, cx, args| { reject_outside_std!(cx); if !this.check_duplicate(cx) @@ -242,10 +254,15 @@ impl AttributeParser for ConstStabilityParser { } }, ), - (&[sym::rustc_promotable], template!(Word), |this, cx, _| { - reject_outside_std!(cx); - this.promotable = true; - }), + ( + &[sym::rustc_promotable], + template!(Word), + gated_rustc_attr!(rustc_promotable), + |this, cx, _| { + reject_outside_std!(cx); + this.promotable = true; + }, + ), ]; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), @@ -483,6 +500,7 @@ pub(crate) struct UnstableRemovedParser; impl CombineAttributeParser for UnstableRemovedParser { type Item = UnstableRemovedFeature; const PATH: &[Symbol] = &[sym::unstable_removed]; + const GATED: AttributeGate = Ungated; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 4fe0f079bc83c..1b2b3c2f3ce22 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -10,6 +10,7 @@ impl SingleAttributeParser for IgnoreParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]); + const GATED: AttributeGate = AttributeGate::Ungated; const TEMPLATE: AttributeTemplate = template!( Word, NameValueStr: "reason", "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute" @@ -55,6 +56,8 @@ impl SingleAttributeParser for ShouldPanicParser { "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute" ); + const GATED: AttributeGate = AttributeGate::Ungated; + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { Some(AttributeKind::ShouldPanic { span: cx.attr_span, @@ -103,6 +106,8 @@ pub(crate) struct ReexportTestHarnessMainParser; impl SingleAttributeParser for ReexportTestHarnessMainParser { const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = + gated!(custom_test_frameworks, "custom test frameworks are an unstable feature"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); @@ -130,6 +135,8 @@ pub(crate) struct RustcAbiParser; impl SingleAttributeParser for RustcAbiParser { const PATH: &[Symbol] = &[sym::rustc_abi]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_abi); + const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::TyAlias), @@ -180,6 +187,8 @@ pub(crate) struct RustcDelayedBugFromInsideQueryParser; impl NoArgsAttributeParser for RustcDelayedBugFromInsideQueryParser { const PATH: &[Symbol] = &[sym::rustc_delayed_bug_from_inside_query]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_delayed_bug_from_inside_query); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDelayedBugFromInsideQuery; } @@ -189,6 +198,8 @@ pub(crate) struct RustcEvaluateWhereClausesParser; impl NoArgsAttributeParser for RustcEvaluateWhereClausesParser { const PATH: &[Symbol] = &[sym::rustc_evaluate_where_clauses]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!(TEST, rustc_evaluate_where_clauses); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -204,6 +215,8 @@ pub(crate) struct TestRunnerParser; impl SingleAttributeParser for TestRunnerParser { const PATH: &[Symbol] = &[sym::test_runner]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = + gated!(custom_test_frameworks, "custom test frameworks are an unstable feature"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["path"]); @@ -224,6 +237,11 @@ pub(crate) struct RustcTestMarkerParser; impl SingleAttributeParser for RustcTestMarkerParser { const PATH: &[Symbol] = &[sym::rustc_test_marker]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_test_marker, + "the `#[rustc_test_marker]` attribute is used internally to track tests" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Const), Allow(Target::Fn), diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 54a95ffd0ea33..09eeaf83856b4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -11,6 +11,12 @@ pub(crate) struct RustcSkipDuringMethodDispatchParser; impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_skip_during_method_dispatch, + "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ + from method dispatch when the receiver is of the following type, for compatibility in \ + editions < 2021 (array) or editions < 2024 (boxed_slice)" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]); @@ -61,6 +67,7 @@ pub(crate) struct RustcParenSugarParser; impl NoArgsAttributeParser for RustcParenSugarParser { const PATH: &[Symbol] = &[sym::rustc_paren_sugar]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(unboxed_closures, "unboxed_closures are still evolving"); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar; } @@ -71,6 +78,7 @@ pub(crate) struct MarkerParser; impl NoArgsAttributeParser for MarkerParser { const PATH: &[Symbol] = &[sym::marker]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const GATED: AttributeGate = gated!(marker_trait_attr, experimental!(marker)); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Trait), Warn(Target::Field), @@ -84,6 +92,10 @@ pub(crate) struct RustcDenyExplicitImplParser; impl NoArgsAttributeParser for RustcDenyExplicitImplParser { const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_deny_explicit_impl, + "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl; } @@ -92,6 +104,11 @@ pub(crate) struct RustcDynIncompatibleTraitParser; impl NoArgsAttributeParser for RustcDynIncompatibleTraitParser { const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_dyn_incompatible_trait, + "`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \ + even if it otherwise satisfies the requirements to be dyn-compatible." + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait; } @@ -102,6 +119,10 @@ pub(crate) struct RustcSpecializationTraitParser; impl NoArgsAttributeParser for RustcSpecializationTraitParser { const PATH: &[Symbol] = &[sym::rustc_specialization_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_specialization_trait, + "the `#[rustc_specialization_trait]` attribute is used to check specializations" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait; } @@ -110,6 +131,10 @@ pub(crate) struct RustcUnsafeSpecializationMarkerParser; impl NoArgsAttributeParser for RustcUnsafeSpecializationMarkerParser { const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_unsafe_specialization_marker, + "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" + ); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcUnsafeSpecializationMarker; } @@ -120,6 +145,11 @@ pub(crate) struct RustcCoinductiveParser; impl NoArgsAttributeParser for RustcCoinductiveParser { const PATH: &[Symbol] = &[sym::rustc_coinductive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_coinductive, + "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoinductive; } @@ -128,6 +158,11 @@ pub(crate) struct RustcAllowIncoherentImplParser; impl NoArgsAttributeParser for RustcAllowIncoherentImplParser { const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated_rustc_attr!( + rustc_allow_incoherent_impl, + "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl" + ); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl; @@ -137,6 +172,7 @@ pub(crate) struct FundamentalParser; impl NoArgsAttributeParser for FundamentalParser { const PATH: &[Symbol] = &[sym::fundamental]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const GATED: AttributeGate = gated!(fundamental); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental; diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 5685a2eccb35d..5fbecdc4543bf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -9,6 +9,7 @@ impl SingleAttributeParser for RustcMacroTransparencyParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Custom(|cx, used, unused| { cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes"); }); + const GATED: AttributeGate = gated_rustc_attr!(rustc_macro_transparency); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["transparent", "semiopaque", "opaque"]); diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs index 98f8cc23b5001..1adc76a1cc1aa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/util.rs +++ b/compiler/rustc_attr_parsing/src/attributes/util.rs @@ -2,7 +2,7 @@ use std::num::IntErrorKind; use rustc_ast::LitKind; use rustc_ast::attr::AttributeExt; -use rustc_feature::is_builtin_attr_name; +use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::RustcVersion; use rustc_hir::limit::Limit; use rustc_span::Symbol; @@ -28,7 +28,12 @@ pub fn parse_version(s: Symbol) -> Option { } pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool { - attr.is_doc_comment().is_some() || attr.name().is_some_and(|name| is_builtin_attr_name(name)) + attr.name().is_some_and(|name| BUILTIN_ATTRIBUTES.contains(&name)) + || attr.is_doc_comment().is_some() +} + +pub fn is_builtin_attr_name(attr_name: Symbol) -> bool { + BUILTIN_ATTRIBUTES.contains(&attr_name) } /// Parse a single integer. diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b28971be3cf3e..616a1dbf6a203 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -8,7 +8,7 @@ use std::sync::LazyLock; use private::Sealed; use rustc_ast::{AttrStyle, MetaItemLit, NodeId}; use rustc_errors::{Diag, Diagnostic, Level, MultiSpan}; -use rustc_feature::{AttrSuggestionStyle, AttributeTemplate}; +use rustc_feature::{AttrSuggestionStyle, AttributeGate, AttributeTemplate}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, HirId}; @@ -77,6 +77,7 @@ pub(super) struct GroupTypeInnerAccept { pub(super) accept_fn: AcceptFn, pub(super) allowed_targets: AllowedTargets, pub(super) safety: AttributeSafety, + pub(super) gated: AttributeGate, pub(super) finalizer: FinalizeFn, } @@ -117,7 +118,7 @@ macro_rules! attribute_parsers { static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default()); }; - for (path, template, accept_fn) in <$names>::ATTRIBUTES { + for (path, template, gated, accept_fn) in <$names>::ATTRIBUTES { match accepters.entry(*path) { Entry::Vacant(e) => { e.insert(GroupTypeInnerAccept { @@ -128,6 +129,7 @@ macro_rules! attribute_parsers { }) }), safety: <$names as crate::attributes::AttributeParser<$stage>>::SAFETY, + gated: *gated, allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, finalizer: Box::new(|cx| { let state = STATE_OBJECT.take(); @@ -451,6 +453,8 @@ pub struct AcceptContext<'f, 'sess, S: Stage> { /// The name of the attribute we're currently accepting. pub(crate) attr_path: AttrPath, + + pub(crate) do_nothing_due_to_gate: bool, } impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { diff --git a/compiler/rustc_attr_parsing/src/feature_gate.rs b/compiler/rustc_attr_parsing/src/feature_gate.rs new file mode 100644 index 0000000000000..98010303fc97b --- /dev/null +++ b/compiler/rustc_attr_parsing/src/feature_gate.rs @@ -0,0 +1,37 @@ +use rustc_feature::{AttributeGate, GateKind, GatedAttribute}; +use rustc_session::parse::feature_err; +use rustc_span::Span; + +use crate::context::Stage; +use crate::{AttributeParser, ShouldEmit}; + +impl<'sess, S: Stage> AttributeParser<'sess, S> { + pub fn check_attribute_gate( + &mut self, + gate: AttributeGate, + span: Span, + ) -> Option { + if matches!(self.stage.should_emit(), ShouldEmit::Nothing) { + return None; + } + let AttributeGate::Gated { + gated_attr: GatedAttribute { feature, message, check, notes }, + kind, + } = gate + else { + return None; + }; + if !matches!(kind, GateKind::Ignore) + && !check(self.features()) + && !span.allows_unstable(feature) + { + #[allow(unused_mut)] + let mut diag = feature_err(self.sess, feature, span, message); + for note in notes { + diag.note(*note); + } + diag.emit(); + } + Some(kind) + } +} diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 85e714a1a917c..140c6385ff9c4 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -4,7 +4,7 @@ use rustc_ast as ast; use rustc_ast::token::DocFragmentKind; use rustc_ast::{AttrItemKind, AttrStyle, NodeId, Safety}; use rustc_errors::{DiagCtxtHandle, MultiSpan}; -use rustc_feature::{AttributeTemplate, Features}; +use rustc_feature::{AttributeGate, AttributeTemplate, Features}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target}; @@ -137,6 +137,7 @@ impl<'sess> AttributeParser<'sess, Early> { template: &AttributeTemplate, allow_expr_metavar: AllowExprMetavar, expected_safety: AttributeSafety, + gated: AttributeGate, ) -> Option { let ast::AttrKind::Normal(normal_attr) = &attr.kind else { panic!("parse_single called on a doc attr") @@ -160,6 +161,7 @@ impl<'sess> AttributeParser<'sess, Early> { path, Some(normal_attr.item.unsafety), expected_safety, + gated, ParsedDescription::Attribute, target_span, target_node_id, @@ -182,6 +184,7 @@ impl<'sess> AttributeParser<'sess, Early> { attr_path: AttrPath, attr_safety: Option, expected_safety: AttributeSafety, + gated: AttributeGate, parsed_description: ParsedDescription, target_span: Span, target_node_id: NodeId, @@ -211,6 +214,8 @@ impl<'sess> AttributeParser<'sess, Early> { &mut emit_lint, ) } + let gate_kind = parser.check_attribute_gate(gated, inner_span); + let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext { shared: SharedContext { cx: &mut parser, @@ -224,6 +229,8 @@ impl<'sess> AttributeParser<'sess, Early> { parsed_description, template, attr_path, + do_nothing_due_to_gate: gate_kind + .is_some_and(|gate| matches!(gate, rustc_feature::GateKind::Ignore)), }; parse_fn(&mut cx, args) } @@ -335,6 +342,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { accept.safety, &mut emit_lint, ); + let gate_kind = self.check_attribute_gate(accept.gated, n.item.span()); let Some(args) = ArgParser::from_attr_args( args, @@ -390,6 +398,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { parsed_description: ParsedDescription::Attribute, template: &accept.template, attr_path: attr_path.clone(), + do_nothing_due_to_gate: gate_kind.is_some_and(|gate| { + matches!(gate, rustc_feature::GateKind::Ignore) + }), }; (accept.accept_fn)(&mut cx, &args); diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 1b08ed3c49b78..85b43566c9b82 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -101,6 +101,7 @@ pub mod parser; mod early_parsed; mod errors; +mod feature_gate; mod safety; mod session_diagnostics; mod target_checking; @@ -111,7 +112,7 @@ pub use attributes::cfg::{ CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry, }; pub use attributes::cfg_select::*; -pub use attributes::util::{is_builtin_attr, parse_version}; +pub use attributes::util::{is_builtin_attr, is_builtin_attr_name, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; pub use session_diagnostics::ParsedDescription; diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index 06ff674f25389..bd4b48aee63b1 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -9,7 +9,7 @@ use rustc_ast::{ self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety, }; use rustc_errors::{Applicability, PResult}; -use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, template}; +use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTES, template}; use rustc_hir::AttrPath; use rustc_hir::lints::AttributeLintKind; use rustc_parse::parse_in; @@ -26,44 +26,40 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { return; } - let builtin_attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)); + if let Some(name) = attr.name() + && BUILTIN_ATTRIBUTES.contains(&name) + { + if AttributeParser::::is_parsed_attribute(slice::from_ref(&name)) { + return; + } + match parse_meta(psess, attr) { + // Don't check safety again, we just did that + Ok(meta) => { + // FIXME The only unparsed builtin attributes that are left are the lint attributes, so we can hardcode the template here + let lint_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect]; + assert!(lint_attrs.contains(&name)); - // Check input tokens for built-in and key-value attributes. - match builtin_attr_info { - Some(BuiltinAttribute { name, .. }) => { - if AttributeParser::::is_parsed_attribute(slice::from_ref(&name)) { - return; + let template = template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ); + check_builtin_meta_item(psess, &meta, attr.style, name, template, false) + } + Err(err) => { + err.emit(); } + } + } else { + let attr_item = attr.get_normal_item(); + if let AttrArgs::Eq { .. } = attr_item.args.unparsed_ref().unwrap() { + // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { - // Don't check safety again, we just did that - Ok(meta) => { - // FIXME The only unparsed builtin attributes that are left are the lint attributes, so we can hardcode the template here - let lint_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect]; - assert!(lint_attrs.contains(name)); - - let template = template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ); - check_builtin_meta_item(psess, &meta, attr.style, *name, template, false) - } + Ok(_) => {} Err(err) => { err.emit(); } } } - _ => { - let attr_item = attr.get_normal_item(); - if let AttrArgs::Eq { .. } = attr_item.args.unparsed_ref().unwrap() { - // All key-value attributes are restricted to meta-item syntax. - match parse_meta(psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); - } - } - } - } } } diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 2872cff0fdc7a..1fc63cd258f5a 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -55,6 +55,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result StripUnconfigured<'a> { &CFG_TEMPLATE, AllowExprMetavar::Yes, AttributeSafety::Normal, + rustc_feature::AttributeGate::Ungated, ) else { // Cfg attribute was not parsable, give up return EvalConfigResult::True; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e915be8fe12bb..e8c89e4efb842 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2226,7 +2226,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { cfg_pos = Some(pos); // a cfg attr found, no need to search anymore break; } else if attr_pos.is_none() - && !name.is_some_and(rustc_feature::is_builtin_attr_name) + && !name.is_some_and(rustc_attr_parsing::is_builtin_attr_name) { attr_pos = Some(pos); // a non-cfg attr found, still may find a cfg attr } @@ -2332,6 +2332,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { &CFG_TEMPLATE, AllowExprMetavar::Yes, AttributeSafety::Normal, + rustc_feature::AttributeGate::Ungated, ) else { // Cfg attribute was not parsable, give up return EvalConfigResult::True; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index cf50b9155cc1f..17b883304d351 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1,9 +1,5 @@ //! Built-in attributes and `cfg` flag gating. -use std::sync::LazyLock; - -use AttributeGate::*; -use rustc_data_structures::fx::FxHashMap; use rustc_hir::AttrStyle; use rustc_span::{Symbol, sym}; @@ -69,20 +65,29 @@ pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg #[derive(Clone, Debug, Copy)] pub enum AttributeGate { /// A gated attribute which requires a feature gate to be enabled. - Gated { - /// The feature gate, for example `#![feature(rustc_attrs)]` for rustc_* attributes. - feature: Symbol, - /// The error message displayed when an attempt is made to use the attribute without its feature gate. - message: &'static str, - /// Check function to be called during the `PostExpansionVisitor` pass. - check: fn(&Features) -> bool, - /// Notes to be displayed when an attempt is made to use the attribute without its feature gate. - notes: &'static [&'static str], - }, + Gated { gated_attr: GatedAttribute, kind: GateKind }, /// Ungated attribute, can be used on all release channels Ungated, } +#[derive(Clone, Debug, Copy)] +pub enum GateKind { + Error, + Ignore, +} + +#[derive(Clone, Debug, Copy)] +pub struct GatedAttribute { + /// The feature gate, for example `#![feature(rustc_attrs)]` for rustc_* attributes. + pub feature: Symbol, + /// The error message displayed when an attempt is made to use the attribute without its feature gate. + pub message: &'static str, + /// Check function to be called during the `PostExpansionVisitor` pass. + pub check: fn(&Features) -> bool, + /// Notes to be displayed when an attempt is made to use the attribute without its feature gate. + pub notes: &'static [&'static str], +} + // FIXME(jdonszelmann): move to rustc_hir::attrs /// A template that the attribute input must match. /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. @@ -186,592 +191,313 @@ macro_rules! template { } }; } -macro_rules! ungated { - ($attr:ident $(,)?) => { - BuiltinAttribute { name: sym::$attr, gate: Ungated } - }; -} - -macro_rules! gated { - ($attr:ident, $gate:ident, $message:expr $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - gate: Gated { - feature: sym::$gate, - message: $message, - check: Features::$gate, - notes: &[], - }, - } - }; - ($attr:ident, $message:expr $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - gate: Gated { - feature: sym::$attr, - message: $message, - check: Features::$attr, - notes: &[], - }, - } - }; -} - -macro_rules! rustc_attr { - (TEST, $attr:ident $(,)?) => { - rustc_attr!( - $attr, - concat!( - "the `#[", - stringify!($attr), - "]` attribute is used for rustc unit tests" - ), - ) - }; - ($attr:ident $(, $notes:expr)* $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - gate: Gated { - feature: sym::rustc_attrs, - message: "use of an internal attribute", - check: Features::rustc_attrs, - notes: &[ - concat!("the `#[", - stringify!($attr), - "]` attribute is an internal implementation detail that will never be stable"), - $($notes),* - ] - }, - } - }; -} - -macro_rules! experimental { - ($attr:ident) => { - concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") - }; -} - pub struct BuiltinAttribute { pub name: Symbol, pub gate: AttributeGate, } /// Attributes that have a special meaning to rustc or rustdoc. -#[rustfmt::skip] -pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ - // ========================================================================== - // Stable attributes: - // ========================================================================== - - // Conditional compilation: - ungated!(cfg), - ungated!(cfg_attr), - - // Testing: - ungated!(ignore), - ungated!(should_panic), - - // Macros: - ungated!(automatically_derived), - ungated!(macro_use), - ungated!(macro_escape), // Deprecated synonym for `macro_use`. - ungated!(macro_export), - ungated!(proc_macro), - ungated!(proc_macro_derive), - ungated!(proc_macro_attribute), - - // Lints: - ungated!(warn), - ungated!(allow), - ungated!(expect), - ungated!(forbid), - ungated!(deny), - ungated!(must_use), - gated!( +pub const BUILTIN_ATTRIBUTES: &[Symbol] = { + use sym::*; + &[ + // ========================================================================== + // Stable attributes: + // ========================================================================== + + // Conditional compilation: + cfg, + cfg_attr, + // Testing: + ignore, + should_panic, + // Macros: + automatically_derived, + macro_use, + macro_escape, // Deprecated synonym for `macro_use`. + macro_export, + proc_macro, + proc_macro_derive, + proc_macro_attribute, + // Lints: + warn, + allow, + expect, + forbid, + deny, + must_use, must_not_suspend, - experimental!(must_not_suspend) - ), - ungated!(deprecated), - - // Crate properties: - ungated!(crate_name), - ungated!(crate_type), - - // ABI, linking, symbols, and FFI - ungated!(link), - ungated!(link_name), - ungated!(no_link), - ungated!(repr), - // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity - gated!(rustc_align,fn_align, experimental!(rustc_align)), - gated!(rustc_align_static,static_align, experimental!(rustc_align_static)), - ungated!(export_name), - ungated!(link_section), - ungated!(no_mangle), - ungated!(used), - ungated!(link_ordinal), - ungated!(naked), - // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. - rustc_attr!( + deprecated, + // Crate properties: + crate_name, + crate_type, + // ABI, linking, symbols, and FFI + link, + link_name, + no_link, + repr, + // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity + rustc_align, + rustc_align_static, + export_name, + link_section, + no_mangle, + used, + link_ordinal, + naked, + export_name, + link_section, + no_mangle, + used, + link_ordinal, + naked, + // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. rustc_pass_indirectly_in_non_rustic_abis, - "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs" - ), - - // Limits: - ungated!(recursion_limit), - ungated!(type_length_limit), - gated!( + // Limits: + recursion_limit, + type_length_limit, move_size_limit, - large_assignments, experimental!(move_size_limit) - ), - - // Entry point: - ungated!(no_main), - - // Modules, prelude, and resolution: - ungated!(path), - ungated!(no_std), - ungated!(no_implicit_prelude), - ungated!(non_exhaustive), - - // Runtime - ungated!(windows_subsystem), - ungated!(// RFC 2070 - panic_handler - ), - // Code generation: - ungated!(inline), - ungated!(cold), - ungated!(no_builtins), - ungated!(target_feature), - ungated!(track_caller), - ungated!(instruction_set), - gated!( + // Entry point: + no_main, + // Modules, prelude, and resolution: + path, + no_std, + no_implicit_prelude, + non_exhaustive, + // Runtime + windows_subsystem, + // RFC 2070 + panic_handler, + // Code generation: + inline, + cold, + no_builtins, + target_feature, + track_caller, + instruction_set, force_target_feature, - effective_target_features, experimental!(force_target_feature) - ), - gated!( sanitize, - sanitize, experimental!(sanitize), - ), - gated!( coverage, - coverage_attribute, experimental!(coverage) - ), - - ungated!(doc), - - // Debugging - ungated!(debugger_visualizer), - ungated!(collapse_debuginfo), - - // ========================================================================== - // Unstable attributes: - // ========================================================================== - - // Linking: - gated!( + doc, + // Debugging + debugger_visualizer, + collapse_debuginfo, + debugger_visualizer, + collapse_debuginfo, + // ========================================================================== + // Unstable attributes: + // ========================================================================== + + // Linking: export_stable, - experimental!(export_stable) - ), - - // Testing: - gated!( + // Testing: test_runner, - custom_test_frameworks, - "custom test frameworks are an unstable feature", - ), - - gated!( reexport_test_harness_main, - custom_test_frameworks, - "custom test frameworks are an unstable feature", - ), - - // RFC #1268 - gated!( + // RFC #1268 marker, - marker_trait_attr, experimental!(marker) - ), - gated!( thread_local, - "`#[thread_local]` is an experimental feature, and does not currently handle destructors", - ), - gated!( no_core, - experimental!(no_core) - ), - // RFC 2412 - gated!( + // RFC 2412 optimize, - optimize_attribute, experimental!(optimize) - ), - - gated!( - ffi_pure, experimental!(ffi_pure) - ), - gated!( - ffi_const, experimental!(ffi_const) - ), - gated!( + ffi_pure, + ffi_const, register_tool, - experimental!(register_tool), - ), - // `#[cfi_encoding = ""]` - gated!( + // `#[cfi_encoding = ""]` cfi_encoding, - experimental!(cfi_encoding) - ), - - // `#[coroutine]` attribute to be applied to closures to make them coroutines instead - gated!( + // `#[coroutine]` attribute to be applied to closures to make them coroutines instead coroutine, - coroutines, experimental!(coroutine) - ), - - // RFC 3543 - // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` - gated!( + // RFC 3543 + // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` patchable_function_entry, - experimental!(patchable_function_entry) - ), - - // The `#[loop_match]` and `#[const_continue]` attributes are part of the - // lang experiment for RFC 3720 tracked in: - // - // - https://github.com/rust-lang/rust/issues/132306 - gated!( + // The `#[loop_match]` and `#[const_continue]` attributes are part of the + // lang experiment for RFC 3720 tracked in: + // + // - https://github.com/rust-lang/rust/issues/132306 const_continue, - loop_match, experimental!(const_continue) - ), - gated!( loop_match, - loop_match, experimental!(loop_match) - ), - - // The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment - // that allows structurally pinning, tracked in: - // - // - https://github.com/rust-lang/rust/issues/130494 - gated!( + // The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment + // that allows structurally pinning, tracked in: + // + // - https://github.com/rust-lang/rust/issues/130494 pin_v2, - pin_ergonomics, experimental!(pin_v2), - ), - - // ========================================================================== - // Internal attributes: Stability, deprecation, and unsafe: - // ========================================================================== - - ungated!(feature), - // DuplicatesOk since it has its own validation - ungated!(stable), - ungated!(unstable), - ungated!(unstable_feature_bound), - ungated!(unstable_removed), - ungated!(rustc_const_unstable), - ungated!(rustc_const_stable), - ungated!(rustc_default_body_unstable), - gated!( + // ========================================================================== + // Internal attributes: Stability, deprecation, and unsafe: + // ========================================================================== + feature, + // DuplicatesOk since it has its own validation + stable, + unstable, + unstable_feature_bound, + unstable_removed, + rustc_const_unstable, + rustc_const_stable, + rustc_default_body_unstable, allow_internal_unstable, - "allow_internal_unstable side-steps feature gating and stability checks", - ), - gated!( allow_internal_unsafe, - "allow_internal_unsafe side-steps the unsafe_code lint", - ), - gated!( rustc_eii_foreign_item, - eii_internals, - "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", - ), - rustc_attr!( rustc_allowed_through_unstable_modules, - "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ - through unstable paths" - ), - rustc_attr!(rustc_deprecated_safe_2024,"`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", - ), - rustc_attr!(rustc_pub_transparent,"used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", - ), - - - // ========================================================================== - // Internal attributes: Type system related: - // ========================================================================== - - gated!(fundamental, experimental!(fundamental)), - gated!( + rustc_deprecated_safe_2024, + rustc_pub_transparent, + // ========================================================================== + // Internal attributes: Type system related: + // ========================================================================== + fundamental, may_dangle, - dropck_eyepatch, - "`may_dangle` has unstable semantics and may be removed in the future", - ), - - rustc_attr!( rustc_never_type_options, - "`rustc_never_type_options` is used to experiment with never type fallback and work on \ - never type stabilization" - ), - - // ========================================================================== - // Internal attributes: Runtime related: - // ========================================================================== - - rustc_attr!(rustc_allocator), - rustc_attr!(rustc_nounwind), - rustc_attr!(rustc_reallocator), - rustc_attr!(rustc_deallocator), - rustc_attr!(rustc_allocator_zeroed), - rustc_attr!(rustc_allocator_zeroed_variant), - gated!( + // ========================================================================== + // Internal attributes: Runtime related: + // ========================================================================== + rustc_allocator, + rustc_nounwind, + rustc_reallocator, + rustc_deallocator, + rustc_allocator_zeroed, + rustc_allocator_zeroed_variant, default_lib_allocator, - allocator_internals, experimental!(default_lib_allocator), - ), - gated!( needs_allocator, - allocator_internals, experimental!(needs_allocator), - ), - gated!( panic_runtime, - experimental!(panic_runtime) - ), - gated!( needs_panic_runtime, - experimental!(needs_panic_runtime) - ), - gated!( compiler_builtins, - "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ - which contains compiler-rt intrinsics and will never be stable", - ), - gated!( profiler_runtime, - "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ - which contains the profiler runtime and will never be stable", - ), - - // ========================================================================== - // Internal attributes, Linkage: - // ========================================================================== - - gated!( + // ========================================================================== + // Internal attributes, Linkage: + // ========================================================================== linkage, - "the `linkage` attribute is experimental and not portable across platforms", - ), - rustc_attr!(rustc_std_internal_symbol), - rustc_attr!(rustc_objc_class), - rustc_attr!(rustc_objc_selector), - - // ========================================================================== - // Internal attributes, Macro related: - // ========================================================================== - - rustc_attr!(rustc_offload_kernel), - rustc_attr!(rustc_builtin_macro), - rustc_attr!(rustc_proc_macro_decls), - rustc_attr!(rustc_macro_transparency, "used internally for testing macro hygiene"), - // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. - // The attributes are not gated, to avoid stability errors, but they cannot be used in stable - // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they - // can only be generated by the compiler. - ungated!(cfg_trace), - ungated!(cfg_attr_trace), - - // ========================================================================== - // Internal attributes, Diagnostics related: - // ========================================================================== - - rustc_attr!( + rustc_std_internal_symbol, + rustc_objc_class, + rustc_objc_selector, + // ========================================================================== + // Internal attributes, Macro related: + // ========================================================================== + rustc_builtin_macro, + rustc_proc_macro_decls, + rustc_macro_transparency, + rustc_autodiff, + rustc_offload_kernel, + // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. + // The attributes are not gated, to avoid stability errors, but they cannot be used in stable + // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they + // can only be generated by the compiler. + cfg_trace, + cfg_attr_trace, + // ========================================================================== + // Internal attributes, Diagnostics related: + // ========================================================================== rustc_on_unimplemented, - "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" - ), - rustc_attr!(rustc_confusables), - // Enumerates "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!(rustc_conversion_suggestion), - // Prevents field reads in the marked trait or method to be considered - // during dead code analysis. - rustc_attr!(rustc_trivial_field_reads), - // Used by the `rustc::potential_query_instability` lint to warn methods which - // might not be stable during incremental compilation. - rustc_attr!(rustc_lint_query_instability), - // Used by the `rustc::untracked_query_information` lint to warn methods which - // might not be stable during incremental compilation. - rustc_attr!(rustc_lint_untracked_query_information), - // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` - // types (as well as any others in future). - rustc_attr!(rustc_lint_opt_ty), - // Used by the `rustc::bad_opt_access` lint on fields - // types (as well as any others in future). - rustc_attr!(rustc_lint_opt_deny_field_access), - - // ========================================================================== - // Internal attributes, Const related: - // ========================================================================== - - rustc_attr!(rustc_promotable), - rustc_attr!(rustc_legacy_const_generics), - // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. - rustc_attr!(rustc_do_not_const_check, "`#[rustc_do_not_const_check]` skips const-check for this function's body"), - rustc_attr!(rustc_const_stable_indirect, "this is an internal implementation detail"), - rustc_attr!(rustc_intrinsic_const_stable_indirect, "this is an internal implementation detail"), - rustc_attr!(rustc_allow_const_fn_unstable, "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"), - - // ========================================================================== - // Internal attributes, Layout related: - // ========================================================================== - - rustc_attr!(rustc_layout_scalar_valid_range_start, "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ - niche optimizations in the standard library"), - rustc_attr!(rustc_layout_scalar_valid_range_end, "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ - niche optimizations in the standard library"), - rustc_attr!(rustc_simd_monomorphize_lane_limit, "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ - for better error messages"), - rustc_attr!(rustc_nonnull_optimization_guaranteed, - "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"), - - // ========================================================================== - // Internal attributes, Misc: - // ========================================================================== - gated!( - lang, lang_items, - "lang items are subject to change", - ), - rustc_attr!(rustc_as_ptr, "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations"), - rustc_attr!(rustc_should_not_be_called_on_const_items, "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts"), - rustc_attr!(rustc_pass_by_value, "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference"), - rustc_attr!(rustc_never_returns_null_ptr, "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers"), - rustc_attr!(rustc_no_implicit_autorefs, "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument"), - rustc_attr!(rustc_coherence_is_core, "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`"), - rustc_attr!(rustc_coinductive, "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver"), - rustc_attr!(rustc_allow_incoherent_impl, "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl"), - rustc_attr!(rustc_preserve_ub_checks, "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR"), - rustc_attr!(rustc_deny_explicit_impl, - "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls" - ), - rustc_attr!( + rustc_confusables, + // Enumerates "identity-like" conversion methods to suggest on type mismatch. + rustc_conversion_suggestion, + // Prevents field reads in the marked trait or method to be considered + // during dead code analysis. + rustc_trivial_field_reads, + // Used by the `rustc::potential_query_instability` lint to warn methods which + // might not be stable during incremental compilation. + rustc_lint_query_instability, + // Used by the `rustc::untracked_query_information` lint to warn methods which + // might not be stable during incremental compilation. + rustc_lint_untracked_query_information, + // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` + // types (as well as any others in future). + rustc_lint_opt_ty, + // Used by the `rustc::bad_opt_access` lint on fields + // types (as well as any others in future). + rustc_lint_opt_deny_field_access, + // ========================================================================== + // Internal attributes, Const related: + // ========================================================================== + rustc_promotable, + rustc_legacy_const_generics, + // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. + rustc_do_not_const_check, + rustc_const_stable_indirect, + rustc_intrinsic_const_stable_indirect, + rustc_allow_const_fn_unstable, + // ========================================================================== + // Internal attributes, Layout related: + // ========================================================================== + rustc_layout_scalar_valid_range_start, + rustc_layout_scalar_valid_range_end, + rustc_simd_monomorphize_lane_limit, + rustc_nonnull_optimization_guaranteed, + // ========================================================================== + // Internal attributes, Misc: + // ========================================================================== + lang, + rustc_as_ptr, + rustc_should_not_be_called_on_const_items, + rustc_pass_by_value, + rustc_never_returns_null_ptr, + rustc_no_implicit_autorefs, + rustc_coherence_is_core, + rustc_coinductive, + rustc_allow_incoherent_impl, + rustc_preserve_ub_checks, + rustc_deny_explicit_impl, rustc_dyn_incompatible_trait, - "`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \ - even if it otherwise satisfies the requirements to be dyn-compatible." - ), - rustc_attr!( rustc_has_incoherent_inherent_impls, - "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ - the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" - ), - rustc_attr!( rustc_non_const_trait_method, - "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ - as non-const to allow large traits an easier transition to const" - ), - - BuiltinAttribute { - name: sym::rustc_diagnostic_item, - gate: Gated { - feature: sym::rustc_attrs, - message: "use of an internal attribute", - check: Features::rustc_attrs, - notes: &["the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \ - from the standard library for diagnostic purposes"], - }, - }, - gated!( - // Used in resolve: + rustc_diagnostic_item, prelude_import, - "`#[prelude_import]` is for use by rustc only", - ), - gated!( rustc_paren_sugar, - unboxed_closures, "unboxed_closures are still evolving", - ), - rustc_attr!( rustc_inherit_overflow_checks, - "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ - overflow checking behavior of several functions in the standard library that are inlined \ - across crates", - ), - rustc_attr!(rustc_reservation_impl,"the `#[rustc_reservation_impl]` attribute is internally used \ - for reserving `impl From for T` as part of the effort to stabilize `!`" - ), - rustc_attr!(rustc_test_marker, "the `#[rustc_test_marker]` attribute is used internally to track tests"), - rustc_attr!(rustc_unsafe_specialization_marker, - "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" - ), - rustc_attr!( + rustc_reservation_impl, + rustc_reservation_impl, + rustc_test_marker, + rustc_unsafe_specialization_marker, rustc_specialization_trait, - "the `#[rustc_specialization_trait]` attribute is used to check specializations" - ), - rustc_attr!(rustc_main,"the `#[rustc_main]` attribute is used internally to specify test entry point function"), - rustc_attr!(rustc_skip_during_method_dispatch, "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ - from method dispatch when the receiver is of the following type, for compatibility in \ - editions < 2021 (array) or editions < 2024 (boxed_slice)" - ), - rustc_attr!(rustc_must_implement_one_of,"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", - ), - rustc_attr!(rustc_doc_primitive,"the `#[rustc_doc_primitive]` attribute is used by the standard library \ - to provide a way to generate documentation for primitive types", - ), - gated!( - rustc_intrinsic,intrinsics, - "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items"), - rustc_attr!(rustc_no_mir_inline,"`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" - ), - rustc_attr!(rustc_force_inline,"`#[rustc_force_inline]` forces a free function to be inlined"), - rustc_attr!(rustc_scalable_vector,"`#[rustc_scalable_vector]` defines a scalable vector type"), - - // ========================================================================== - // Internal attributes, Testing: - // ========================================================================== - - rustc_attr!(TEST, rustc_effective_visibility), - rustc_attr!(TEST, rustc_dump_inferred_outlives), - rustc_attr!(TEST, rustc_capture_analysis), - rustc_attr!(TEST, rustc_insignificant_dtor), - rustc_attr!(TEST, rustc_no_implicit_bounds), - rustc_attr!(TEST, rustc_strict_coherence), - rustc_attr!(TEST, rustc_dump_variances), - rustc_attr!(TEST, rustc_dump_variances_of_opaques), - //rustc_attr!(TEST, rustc_hidden_type_of_opaques), - //rustc_attr!(TEST, rustc_layout), - rustc_attr!(TEST, rustc_abi), - rustc_attr!(TEST, rustc_regions), - rustc_attr!(TEST, rustc_delayed_bug_from_inside_query), - rustc_attr!(TEST, rustc_dump_user_args), - rustc_attr!(TEST, rustc_evaluate_where_clauses), - rustc_attr!(TEST, rustc_if_this_changed), - rustc_attr!(TEST, rustc_then_this_would_need), - rustc_attr!(TEST, rustc_clean), - rustc_attr!(TEST, rustc_partition_reused), - rustc_attr!(TEST, rustc_partition_codegened), - rustc_attr!(TEST, rustc_expected_cgu_reuse), - //rustc_attr!(TEST, rustc_symbol_name), - //rustc_attr!(TEST, rustc_def_path), - rustc_attr!(TEST, rustc_mir), - gated!(custom_mir,"the `#[custom_mir]` attribute is just used for the Rust test suite"), - rustc_attr!(TEST, rustc_dump_item_bounds), - rustc_attr!(TEST, rustc_dump_predicates), - rustc_attr!(TEST, rustc_dump_def_parents), - rustc_attr!(TEST, rustc_dump_object_lifetime_defaults), - rustc_attr!(TEST, rustc_dump_vtable), - rustc_attr!(TEST, rustc_dummy), - rustc_attr!(TEST, pattern_complexity_limit), -]; - -pub fn is_builtin_attr_name(name: Symbol) -> bool { - BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() + rustc_main, + rustc_main, + rustc_skip_during_method_dispatch, + rustc_must_implement_one_of, + rustc_doc_primitive, + rustc_intrinsic, + rustc_no_mir_inline, + rustc_force_inline, + rustc_scalable_vector, + rustc_must_match_exhaustively, + // ========================================================================== + // Internal attributes, Testing: + // ========================================================================== + rustc_effective_visibility, + rustc_dump_inferred_outlives, + rustc_capture_analysis, + rustc_insignificant_dtor, + rustc_no_implicit_bounds, + rustc_strict_coherence, + rustc_dump_variances, + rustc_dump_variances_of_opaques, + rustc_dump_hidden_type_of_opaques, + rustc_dump_layout, + rustc_abi, + rustc_regions, + rustc_delayed_bug_from_inside_query, + rustc_dump_user_args, + rustc_evaluate_where_clauses, + rustc_if_this_changed, + rustc_then_this_would_need, + rustc_clean, + rustc_expected_cgu_reuse, + rustc_dump_symbol_name, + rustc_dump_def_path, + rustc_mir, + custom_mir, + rustc_dump_item_bounds, + rustc_dump_predicates, + rustc_dump_def_parents, + rustc_dump_object_lifetime_defaults, + rustc_dump_vtable, + rustc_dummy, + pattern_complexity_limit, + // FIXME find correct place + rustc_partition_reused, + rustc_partition_codegened, + ] +}; + +pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool { + match sym { + sym::on_unimplemented | sym::do_not_recommend => true, + sym::on_const => features.diagnostic_on_const(), + sym::on_move => features.diagnostic_on_move(), + _ => false, + } } - -pub static BUILTIN_ATTRIBUTE_MAP: LazyLock> = - LazyLock::new(|| { - let mut map = FxHashMap::default(); - for attr in BUILTIN_ATTRIBUTES.iter() { - if map.insert(attr.name, attr).is_some() { - panic!("duplicate builtin attribute `{}`", attr.name); - } - } - map - }); diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index ce3ce6fcccee4..ad602521a734f 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -129,8 +129,8 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option(expr: Result>>) -> T { /// /// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`, /// etc., otherwise a panic will occur when they are dropped. -pub fn new_parser_from_source_str( - psess: &ParseSess, +pub fn new_parser_from_source_str<'sess>( + psess: &'sess ParseSess, name: FileName, source: String, strip_tokens: StripTokens, -) -> Result, Vec>> { +) -> Result, Vec>> { let source_file = psess.source_map().new_source_file(name, source); new_parser_from_source_file(psess, source_file, strip_tokens) } @@ -186,11 +186,11 @@ pub fn utf8_error( /// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing /// the initial token stream. -fn new_parser_from_source_file( - psess: &ParseSess, +fn new_parser_from_source_file<'sess>( + psess: &'sess ParseSess, source_file: Arc, strip_tokens: StripTokens, -) -> Result, Vec>> { +) -> Result, Vec>> { let end_pos = source_file.end_position(); let stream = source_file_to_stream(psess, source_file, None, strip_tokens)?; let mut parser = Parser::new(psess, stream, None); diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index e04178645fdd8..a6ca751b9b580 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -8,8 +8,9 @@ use rustc_ast::tokenstream::{ use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, HasTokens}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::PResult; +use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_session::parse::ParseSess; -use rustc_span::{DUMMY_SP, sym}; +use rustc_span::{DUMMY_SP, Symbol, sym}; use thin_vec::ThinVec; use super::{Capturing, ForceCollect, Parser, Trailing}; @@ -152,7 +153,7 @@ impl<'a> Parser<'a> { // tokens by definition). let needs_collection = matches!(force_collect, ForceCollect::Yes) // - Any of our outer attributes require tokens. - || needs_tokens(&attrs.attrs) + || needs_tokens(&attrs.attrs, BUILTIN_ATTRIBUTES) // - Our target supports custom inner attributes (custom // inner attribute invocation might require token capturing). || R::SUPPORTS_CUSTOM_INNER_ATTRS @@ -239,7 +240,7 @@ impl<'a> Parser<'a> { // outer and inner attributes. So this check is more precise than // the earlier `needs_tokens` check, and we don't need to // check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.) - || needs_tokens(&ret_attrs) + || needs_tokens(&ret_attrs, BUILTIN_ATTRIBUTES) // - We are in "definite capture mode", which requires that there // are `#[cfg]` or `#[cfg_attr]` attributes. (During normal // non-`capture_cfg` parsing, we don't need any special capturing @@ -397,9 +398,9 @@ impl<'a> Parser<'a> { /// - any `cfg_attr` attributes are present; or /// - any single-segment, non-builtin attributes are present, e.g. `derive`, /// `test`, `global_allocator`. -fn needs_tokens(attrs: &[ast::Attribute]) -> bool { +fn needs_tokens(attrs: &[ast::Attribute], valid_names: &'static [Symbol]) -> bool { attrs.iter().any(|attr| match attr.name() { None => !attr.is_doc_comment(), - Some(name) => name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(name), + Some(name) => name == sym::cfg_attr || !valid_names.contains(&name), }) } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c7a3ee456f88d..7ddedb26a11b1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -14,7 +14,7 @@ use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, msg}; -use rustc_feature::BUILTIN_ATTRIBUTE_MAP; +use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::attrs::diagnostic::Directive; use rustc_hir::attrs::{ AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, @@ -400,21 +400,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .. ] => {} [name, rest@..] => { - match BUILTIN_ATTRIBUTE_MAP.get(name) { - Some(_) => { - if rest.len() > 0 && AttributeParser::::is_parsed_attribute(slice::from_ref(name)) { - // Check if we tried to use a builtin attribute as an attribute namespace, like `#[must_use::skip]`. - // This check is here to solve https://github.com/rust-lang/rust/issues/137590 - // An error is already produced for this case elsewhere - continue - } - - span_bug!( - attr.span(), - "builtin attribute {name:?} not handled by `CheckAttrVisitor`" - ) + if BUILTIN_ATTRIBUTES.contains(&name) { + if rest.len() > 0 && AttributeParser::::is_parsed_attribute(slice::from_ref(name)) { + // Check if we tried to use a builtin attribute as an attribute namespace, like `#[must_use::skip]`. + // This check is here to solve https://github.com/rust-lang/rust/issues/137590 + // An error is already produced for this case elsewhere + continue } - None => (), + + // FIXME: bring this back when we do whole name parsing on BUILTIN_ATTR_NAMES + span_bug!( + attr.span(), + "builtin attribute {name:?} not handled by `CheckAttrVisitor`" + ) } } [] => unreachable!(), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4d855037ca170..b108034dc5af1 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1246,7 +1246,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() - .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)), + .copied() + .map(|attr| TypoSuggestion::typo_from_name(attr, res)), ); } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7334131a1c01d..28447185ff904 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1709,10 +1709,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .collect(), builtin_attr_decls: BUILTIN_ATTRIBUTES .iter() + .copied() .map(|builtin_attr| { - let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr.name)); + let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr)); let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT); - (builtin_attr.name, decl) + (builtin_attr, decl) }) .collect(), registered_tool_decls: registered_tools diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 4b64771eff80d..efa3331536bde 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -124,15 +124,6 @@ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `p LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ -error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:219:1 - | -LL | #[allow_internal_unsafe = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0539]: malformed `windows_subsystem` attribute input --> $DIR/malformed-attrs.rs:26:1 | @@ -675,6 +666,15 @@ LL - #[macro_export = 18] LL + #[macro_export] | +error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint + --> $DIR/malformed-attrs.rs:219:3 + | +LL | #[allow_internal_unsafe = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0565]: malformed `allow_internal_unsafe` attribute input --> $DIR/malformed-attrs.rs:219:1 | diff --git a/tests/ui/attributes/malformed-never-type-options.stderr b/tests/ui/attributes/malformed-never-type-options.stderr index 98870c8bddedc..446a4f30be7db 100644 --- a/tests/ui/attributes/malformed-never-type-options.stderr +++ b/tests/ui/attributes/malformed-never-type-options.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/malformed-never-type-options.rs:4:1 + --> $DIR/malformed-never-type-options.rs:4:4 | LL | #![rustc_never_type_options(: Unsize = "hi")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_never_type_options]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/consts/gate-do-not-const-check.stderr b/tests/ui/consts/gate-do-not-const-check.stderr index 778ee50e71b6d..71d47b9a0dc52 100644 --- a/tests/ui/consts/gate-do-not-const-check.stderr +++ b/tests/ui/consts/gate-do-not-const-check.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/gate-do-not-const-check.rs:1:1 + --> $DIR/gate-do-not-const-check.rs:1:3 | LL | #[rustc_do_not_const_check] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_do_not_const_check]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/coroutine/gen_block.e2024.stderr b/tests/ui/coroutine/gen_block.e2024.stderr index 347f111e79fdc..50484a6c07e99 100644 --- a/tests/ui/coroutine/gen_block.e2024.stderr +++ b/tests/ui/coroutine/gen_block.e2024.stderr @@ -1,34 +1,34 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/gen_block.rs:16:16 + | +LL | let _ = || yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | let _ = #[coroutine] || yield true; + | ++++++++++++ + error[E0658]: the `#[coroutine]` attribute is an experimental feature - --> $DIR/gen_block.rs:20:13 + --> $DIR/gen_block.rs:20:15 | LL | let _ = #[coroutine] || yield true; - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: see issue #43122 for more information = help: add `#![feature(coroutines)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[coroutine]` attribute is an experimental feature - --> $DIR/gen_block.rs:24:13 + --> $DIR/gen_block.rs:24:15 | LL | let _ = #[coroutine] || {}; - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: see issue #43122 for more information = help: add `#![feature(coroutines)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - --> $DIR/gen_block.rs:16:16 - | -LL | let _ = || yield true; - | ^^^^^^^^^^ - | -help: use `#[coroutine]` to make this closure a coroutine - | -LL | let _ = #[coroutine] || yield true; - | ++++++++++++ - error[E0282]: type annotations needed --> $DIR/gen_block.rs:7:13 | diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr index b793033b5216a..4b85a0818e5f5 100644 --- a/tests/ui/coroutine/gen_block.none.stderr +++ b/tests/ui/coroutine/gen_block.none.stderr @@ -44,26 +44,6 @@ LL | let _ = #[coroutine] || yield true; = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the `#[coroutine]` attribute is an experimental feature - --> $DIR/gen_block.rs:20:13 - | -LL | let _ = #[coroutine] || yield true; - | ^^^^^^^^^^^^ - | - = note: see issue #43122 for more information - = help: add `#![feature(coroutines)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: the `#[coroutine]` attribute is an experimental feature - --> $DIR/gen_block.rs:24:13 - | -LL | let _ = #[coroutine] || {}; - | ^^^^^^^^^^^^ - | - = note: see issue #43122 for more information - = help: add `#![feature(coroutines)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: yield syntax is experimental --> $DIR/gen_block.rs:16:16 | @@ -85,6 +65,16 @@ help: use `#[coroutine]` to make this closure a coroutine LL | let _ = #[coroutine] || yield true; | ++++++++++++ +error[E0658]: the `#[coroutine]` attribute is an experimental feature + --> $DIR/gen_block.rs:20:15 + | +LL | let _ = #[coroutine] || yield true; + | ^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: yield syntax is experimental --> $DIR/gen_block.rs:20:29 | @@ -95,6 +85,16 @@ LL | let _ = #[coroutine] || yield true; = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: the `#[coroutine]` attribute is an experimental feature + --> $DIR/gen_block.rs:24:15 + | +LL | let _ = #[coroutine] || {}; + | ^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error: aborting due to 11 previous errors Some errors have detailed explanations: E0422, E0658. diff --git a/tests/ui/feature-gates/feature-gate-allocator_internals.stderr b/tests/ui/feature-gates/feature-gate-allocator_internals.stderr index 905c0252484bf..83c38f2f7e9ac 100644 --- a/tests/ui/feature-gates/feature-gate-allocator_internals.stderr +++ b/tests/ui/feature-gates/feature-gate-allocator_internals.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[default_lib_allocator]` attribute is an experimental feature - --> $DIR/feature-gate-allocator_internals.rs:1:1 + --> $DIR/feature-gate-allocator_internals.rs:1:4 | LL | #![default_lib_allocator] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(allocator_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr index 7a0dcb0843590..97bb53d09773f 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:8:9 + --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:8:11 | LL | #[allow_internal_unsafe] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | bar!(); | ------ in this macro invocation diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr index 4aacfebd6b1fa..d02832c6aee24 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks - --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:8:9 + --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:8:11 | LL | #[allow_internal_unstable()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bar!(); | ------ in this macro invocation diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr index d68affa955aa8..4a186ca217d20 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks - --> $DIR/feature-gate-allow-internal-unstable-struct.rs:6:1 + --> $DIR/feature-gate-allow-internal-unstable-struct.rs:6:3 | LL | #[allow_internal_unstable(something)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr index 3e3ecc1e5bab1..84c1462f404cf 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks - --> $DIR/feature-gate-allow-internal-unstable.rs:3:1 + --> $DIR/feature-gate-allow-internal-unstable.rs:3:3 | LL | #[allow_internal_unstable()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr b/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr index ae5efc0275f21..fa9f4d3d05128 100644 --- a/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr +++ b/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[cfi_encoding]` attribute is an experimental feature - --> $DIR/feature-gate-cfi_encoding.rs:3:1 + --> $DIR/feature-gate-cfi_encoding.rs:3:3 | LL | #[cfi_encoding = "3Bar"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #89653 for more information = help: add `#![feature(cfi_encoding)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr b/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr index cc3dda7c1f09a..7b9b8e05e18bc 100644 --- a/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr +++ b/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks - --> $DIR/feature-gate-check-nested-macro-invocation.rs:8:9 + --> $DIR/feature-gate-check-nested-macro-invocation.rs:8:11 | LL | #[allow_internal_unstable()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | foo!(); | ------ in this macro invocation diff --git a/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr b/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr index 65137a442b043..cb8c941fa05f9 100644 --- a/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr +++ b/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable - --> $DIR/feature-gate-compiler-builtins.rs:1:1 + --> $DIR/feature-gate-compiler-builtins.rs:1:4 | LL | #![compiler_builtins] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = help: add `#![feature(compiler_builtins)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr index 68d0d9bc3c31e..6369481af2568 100644 --- a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr @@ -8,10 +8,10 @@ LL | #![feature(no_coverage)] = note: renamed to `coverage_attribute` error[E0658]: the `#[coverage]` attribute is an experimental feature - --> $DIR/feature-gate-coverage-attribute.rs:10:1 + --> $DIR/feature-gate-coverage-attribute.rs:10:3 | LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: see issue #84605 for more information = help: add `#![feature(coverage_attribute)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr index eeceb0355ee7b..afc5c00305995 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite - --> $DIR/feature-gate-custom_mir.rs:6:1 + --> $DIR/feature-gate-custom_mir.rs:6:3 | LL | #[custom_mir(dialect = "built")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(custom_mir)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr index 3e60d33829fc5..499fe388dc5c2 100644 --- a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr @@ -9,20 +9,20 @@ LL | #[test_case] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: custom test frameworks are an unstable feature - --> $DIR/feature-gate-custom_test_frameworks.rs:1:1 + --> $DIR/feature-gate-custom_test_frameworks.rs:1:4 | LL | #![test_runner(main)] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = note: see issue #50297 for more information = help: add `#![feature(custom_test_frameworks)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: custom test frameworks are an unstable feature - --> $DIR/feature-gate-custom_test_frameworks.rs:2:1 + --> $DIR/feature-gate-custom_test_frameworks.rs:2:4 | LL | #![reexport_test_harness_main = "foo"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #50297 for more information = help: add `#![feature(custom_test_frameworks)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr index 19babe149d9a4..2f7bd4f6f3d9a 100644 --- a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr +++ b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr @@ -8,6 +8,30 @@ LL | #[derive(CoercePointee)] = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0659]: `pointee` is ambiguous + --> $DIR/feature-gate-derive-coerce-pointee.rs:5:24 + | +LL | struct MyPointer<'a, #[pointee] T: ?Sized> { + | ^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `pointee` could refer to a built-in attribute +note: `pointee` could also refer to the derive helper attribute defined here + --> $DIR/feature-gate-derive-coerce-pointee.rs:3:10 + | +LL | #[derive(CoercePointee)] + | ^^^^^^^^^^^^^ + +error[E0658]: the `#[pointee]` attribute is an experimental feature + --> $DIR/feature-gate-derive-coerce-pointee.rs:5:24 + | +LL | struct MyPointer<'a, #[pointee] T: ?Sized> { + | ^^^^^^^ + | + = note: see issue #123430 for more information + = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: use of unstable library feature `derive_coerce_pointee` --> $DIR/feature-gate-derive-coerce-pointee.rs:1:5 | @@ -18,6 +42,7 @@ LL | use std::marker::CoercePointee; = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0658, E0659. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr b/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr index e699c5d77b42c..75797a59036e2 100644 --- a/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr +++ b/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[force_target_feature]` attribute is an experimental feature - --> $DIR/feature-gate-effective-target-features.rs:14:5 + --> $DIR/feature-gate-effective-target-features.rs:14:14 | LL | #[unsafe(force_target_feature(enable = "avx2"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #143352 for more information = help: add `#![feature(effective_target_features)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-export_stable.stderr b/tests/ui/feature-gates/feature-gate-export_stable.stderr index 6beb52a77e5cc..53c4bd1b8b245 100644 --- a/tests/ui/feature-gates/feature-gate-export_stable.stderr +++ b/tests/ui/feature-gates/feature-gate-export_stable.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[export_stable]` attribute is an experimental feature - --> $DIR/feature-gate-export_stable.rs:3:1 + --> $DIR/feature-gate-export_stable.rs:3:3 | LL | #[export_stable] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: see issue #139939 for more information = help: add `#![feature(export_stable)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.stderr b/tests/ui/feature-gates/feature-gate-ffi_const.stderr index 7e8c941be07de..55cdb347f2d5d 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_const.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_const.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[ffi_const]` attribute is an experimental feature - --> $DIR/feature-gate-ffi_const.rs:4:5 + --> $DIR/feature-gate-ffi_const.rs:4:14 | LL | #[unsafe(ffi_const)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: see issue #58328 for more information = help: add `#![feature(ffi_const)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr index cf923536d6c55..7f1128cab9737 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[ffi_pure]` attribute is an experimental feature - --> $DIR/feature-gate-ffi_pure.rs:4:5 + --> $DIR/feature-gate-ffi_pure.rs:4:14 | LL | #[unsafe(ffi_pure)] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: see issue #58329 for more information = help: add `#![feature(ffi_pure)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-fn_align.stderr b/tests/ui/feature-gates/feature-gate-fn_align.stderr index 6196f4f298fdc..623840238308d 100644 --- a/tests/ui/feature-gates/feature-gate-fn_align.stderr +++ b/tests/ui/feature-gates/feature-gate-fn_align.stderr @@ -1,18 +1,18 @@ error[E0658]: the `#[rustc_align]` attribute is an experimental feature - --> $DIR/feature-gate-fn_align.rs:7:1 + --> $DIR/feature-gate-fn_align.rs:7:3 | LL | #[rustc_align(16)] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: see issue #82232 for more information = help: add `#![feature(fn_align)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[rustc_align]` attribute is an experimental feature - --> $DIR/feature-gate-fn_align.rs:12:5 + --> $DIR/feature-gate-fn_align.rs:12:7 | LL | #[rustc_align] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: see issue #82232 for more information = help: add `#![feature(fn_align)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-fundamental.stderr b/tests/ui/feature-gates/feature-gate-fundamental.stderr index 61b30dfb29cd8..4e408483b4624 100644 --- a/tests/ui/feature-gates/feature-gate-fundamental.stderr +++ b/tests/ui/feature-gates/feature-gate-fundamental.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[fundamental]` attribute is an experimental feature - --> $DIR/feature-gate-fundamental.rs:1:1 + --> $DIR/feature-gate-fundamental.rs:1:3 | LL | #[fundamental] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: see issue #29635 for more information = help: add `#![feature(fundamental)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr index a7a725883a928..d3da3758242ad 100644 --- a/tests/ui/feature-gates/feature-gate-intrinsics.stderr +++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items - --> $DIR/feature-gate-intrinsics.rs:1:1 + --> $DIR/feature-gate-intrinsics.rs:1:3 | LL | #[rustc_intrinsic] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-lang-items.stderr b/tests/ui/feature-gates/feature-gate-lang-items.stderr index c5caffbdc94dd..f6adb3a21115a 100644 --- a/tests/ui/feature-gates/feature-gate-lang-items.stderr +++ b/tests/ui/feature-gates/feature-gate-lang-items.stderr @@ -1,8 +1,8 @@ error[E0658]: lang items are subject to change - --> $DIR/feature-gate-lang-items.rs:1:1 + --> $DIR/feature-gate-lang-items.rs:1:3 | LL | #[lang = "foo"] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(lang_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.stderr b/tests/ui/feature-gates/feature-gate-large-assignments.stderr index 7b0b4470c4e1e..1a1b9a1f21ff1 100644 --- a/tests/ui/feature-gates/feature-gate-large-assignments.stderr +++ b/tests/ui/feature-gates/feature-gate-large-assignments.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[move_size_limit]` attribute is an experimental feature - --> $DIR/feature-gate-large-assignments.rs:3:1 + --> $DIR/feature-gate-large-assignments.rs:3:4 | LL | #![move_size_limit = "42"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #83518 for more information = help: add `#![feature(large_assignments)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-linkage.stderr b/tests/ui/feature-gates/feature-gate-linkage.stderr index 2044b8a3c2470..f67606d21f442 100644 --- a/tests/ui/feature-gates/feature-gate-linkage.stderr +++ b/tests/ui/feature-gates/feature-gate-linkage.stderr @@ -1,8 +1,8 @@ error[E0658]: the `linkage` attribute is experimental and not portable across platforms - --> $DIR/feature-gate-linkage.rs:2:5 + --> $DIR/feature-gate-linkage.rs:2:7 | LL | #[linkage = "extern_weak"] static foo: *mut isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29603 for more information = help: add `#![feature(linkage)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-loop-match.stderr b/tests/ui/feature-gates/feature-gate-loop-match.stderr index 9b12047cf4dde..ac20166786f79 100644 --- a/tests/ui/feature-gates/feature-gate-loop-match.stderr +++ b/tests/ui/feature-gates/feature-gate-loop-match.stderr @@ -1,28 +1,28 @@ error[E0658]: the `#[loop_match]` attribute is an experimental feature - --> $DIR/feature-gate-loop-match.rs:12:5 + --> $DIR/feature-gate-loop-match.rs:12:7 | LL | #[loop_match] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = note: see issue #132306 for more information = help: add `#![feature(loop_match)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[const_continue]` attribute is an experimental feature - --> $DIR/feature-gate-loop-match.rs:17:21 + --> $DIR/feature-gate-loop-match.rs:17:23 | LL | #[const_continue] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: see issue #132306 for more information = help: add `#![feature(loop_match)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[const_continue]` attribute is an experimental feature - --> $DIR/feature-gate-loop-match.rs:22:21 + --> $DIR/feature-gate-loop-match.rs:22:23 | LL | #[const_continue] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: see issue #132306 for more information = help: add `#![feature(loop_match)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr index 15888a38589cb..92e76e0c19294 100644 --- a/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr +++ b/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[marker]` attribute is an experimental feature - --> $DIR/feature-gate-marker_trait_attr.rs:3:1 + --> $DIR/feature-gate-marker_trait_attr.rs:3:3 | LL | #[marker] trait ExplicitMarker {} - | ^^^^^^^^^ + | ^^^^^^ | = note: see issue #29864 for more information = help: add `#![feature(marker_trait_attr)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-may-dangle.stderr b/tests/ui/feature-gates/feature-gate-may-dangle.stderr index 67d00714d95c5..38b86fc7d02ff 100644 --- a/tests/ui/feature-gates/feature-gate-may-dangle.stderr +++ b/tests/ui/feature-gates/feature-gate-may-dangle.stderr @@ -1,8 +1,8 @@ error[E0658]: `may_dangle` has unstable semantics and may be removed in the future - --> $DIR/feature-gate-may-dangle.rs:6:13 + --> $DIR/feature-gate-may-dangle.rs:6:15 | LL | unsafe impl<#[may_dangle] A> Drop for Pt { - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = note: see issue #34761 for more information = help: add `#![feature(dropck_eyepatch)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-needs-allocator.stderr b/tests/ui/feature-gates/feature-gate-needs-allocator.stderr index f26243de25f38..76aa6fa1bdb9d 100644 --- a/tests/ui/feature-gates/feature-gate-needs-allocator.stderr +++ b/tests/ui/feature-gates/feature-gate-needs-allocator.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[needs_allocator]` attribute is an experimental feature - --> $DIR/feature-gate-needs-allocator.rs:1:1 + --> $DIR/feature-gate-needs-allocator.rs:1:4 | LL | #![needs_allocator] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: add `#![feature(allocator_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-no_core.stderr b/tests/ui/feature-gates/feature-gate-no_core.stderr index f5f04c346aef7..64ab8a15b81f8 100644 --- a/tests/ui/feature-gates/feature-gate-no_core.stderr +++ b/tests/ui/feature-gates/feature-gate-no_core.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[no_core]` attribute is an experimental feature - --> $DIR/feature-gate-no_core.rs:3:1 + --> $DIR/feature-gate-no_core.rs:3:4 | LL | #![no_core] - | ^^^^^^^^^^^ + | ^^^^^^^ | = note: see issue #29639 for more information = help: add `#![feature(no_core)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index 646abf8e4a16e..f9f4300c18724 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -1,38 +1,38 @@ error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:3:1 + --> $DIR/feature-gate-optimize_attribute.rs:3:3 | LL | #[optimize(size)] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:6:1 + --> $DIR/feature-gate-optimize_attribute.rs:6:3 | LL | #[optimize(speed)] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:9:1 + --> $DIR/feature-gate-optimize_attribute.rs:9:3 | LL | #[optimize(none)] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:12:1 + --> $DIR/feature-gate-optimize_attribute.rs:12:3 | LL | #[optimize(banana)] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr b/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr index 55fcdb4f7291e..8cf0fa130091c 100644 --- a/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr +++ b/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[patchable_function_entry]` attribute is an experimental feature - --> $DIR/feature-gate-patchable-function-entry.rs:1:1 + --> $DIR/feature-gate-patchable-function-entry.rs:1:3 | LL | #[patchable_function_entry(prefix_nops = 1, entry_nops = 1)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #123115 for more information = help: add `#![feature(patchable_function_entry)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr index 9ddea866ea997..1a1922ff6a60d 100644 --- a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr +++ b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/feature-gate-pattern-complexity-limit.rs:3:1 + --> $DIR/feature-gate-pattern-complexity-limit.rs:3:4 | LL | #![pattern_complexity_limit = "42"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[pattern_complexity_limit]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr index b721654a506f0..183ace9173191 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr @@ -269,10 +269,10 @@ LL | ref pin const w: i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[pin_v2]` attribute is an experimental feature - --> $DIR/feature-gate-pin_ergonomics.rs:5:1 + --> $DIR/feature-gate-pin_ergonomics.rs:5:3 | LL | #[pin_v2] - | ^^^^^^^^^ + | ^^^^^^ | = note: see issue #130494 for more information = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-prelude_import.stderr b/tests/ui/feature-gates/feature-gate-prelude_import.stderr index 3b22c65cd1fcd..64e4836b1964e 100644 --- a/tests/ui/feature-gates/feature-gate-prelude_import.stderr +++ b/tests/ui/feature-gates/feature-gate-prelude_import.stderr @@ -1,8 +1,8 @@ error[E0658]: `#[prelude_import]` is for use by rustc only - --> $DIR/feature-gate-prelude_import.rs:1:1 + --> $DIR/feature-gate-prelude_import.rs:1:3 | LL | #[prelude_import] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: add `#![feature(prelude_import)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr b/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr index 23792fb09baf7..8d2544472a599 100644 --- a/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr +++ b/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable - --> $DIR/feature-gate-profiler-runtime.rs:1:1 + --> $DIR/feature-gate-profiler-runtime.rs:1:4 | LL | #![profiler_runtime] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(profiler_runtime)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-register_tool.stderr b/tests/ui/feature-gates/feature-gate-register_tool.stderr index a0db6ba744670..ce99384abcad9 100644 --- a/tests/ui/feature-gates/feature-gate-register_tool.stderr +++ b/tests/ui/feature-gates/feature-gate-register_tool.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[register_tool]` attribute is an experimental feature - --> $DIR/feature-gate-register_tool.rs:1:1 + --> $DIR/feature-gate-register_tool.rs:1:4 | LL | #![register_tool(tool)] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #66079 for more information = help: add `#![feature(register_tool)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr index 42424abcc3cb6..5bdf935d1a3f6 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/feature-gate-rustc-allow-const-fn-unstable.rs:3:1 + --> $DIR/feature-gate-rustc-allow-const-fn-unstable.rs:3:3 | LL | #[rustc_allow_const_fn_unstable()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_allow_const_fn_unstable]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr index 81d8a750b897a..254038f1d56ba 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/feature-gate-rustc-attrs-1.rs:3:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:3:3 | LL | #[rustc_nonnull_optimization_guaranteed] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_nonnull_optimization_guaranteed]` attribute is an internal implementation detail that will never be stable @@ -10,10 +10,10 @@ LL | #[rustc_nonnull_optimization_guaranteed] = note: 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 error[E0658]: use of an internal attribute - --> $DIR/feature-gate-rustc-attrs-1.rs:10:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:10:3 | LL | #[rustc_dump_variances] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_dump_variances]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr index bc0db8b81aefc..953a6b9e867dd 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -35,10 +35,10 @@ LL | #[rustc_unknown] | ^^^^^^^^^^^^^ error[E0658]: use of an internal attribute - --> $DIR/feature-gate-rustc-attrs.rs:20:1 + --> $DIR/feature-gate-rustc-attrs.rs:20:3 | LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_dummy]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/feature-gates/feature-gate-sanitize.stderr b/tests/ui/feature-gates/feature-gate-sanitize.stderr index 59e8b69de2e3d..7bb301b7cac50 100644 --- a/tests/ui/feature-gates/feature-gate-sanitize.stderr +++ b/tests/ui/feature-gates/feature-gate-sanitize.stderr @@ -8,10 +8,10 @@ LL | #![feature(no_sanitize)] = note: renamed to sanitize(xyz = "on|off") error[E0658]: the `#[sanitize]` attribute is an experimental feature - --> $DIR/feature-gate-sanitize.rs:3:1 + --> $DIR/feature-gate-sanitize.rs:3:3 | LL | #[sanitize(address = "on")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #39699 for more information = help: add `#![feature(sanitize)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-static_align.stderr b/tests/ui/feature-gates/feature-gate-static_align.stderr index b45fcdefc9cdf..46bd21ae566e6 100644 --- a/tests/ui/feature-gates/feature-gate-static_align.stderr +++ b/tests/ui/feature-gates/feature-gate-static_align.stderr @@ -1,18 +1,18 @@ error[E0658]: the `#[rustc_align_static]` attribute is an experimental feature - --> $DIR/feature-gate-static_align.rs:3:1 + --> $DIR/feature-gate-static_align.rs:3:3 | LL | #[rustc_align_static(16)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #146177 for more information = help: add `#![feature(static_align)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[rustc_align_static]` attribute is an experimental feature - --> $DIR/feature-gate-static_align.rs:8:5 + --> $DIR/feature-gate-static_align.rs:8:7 | LL | #[rustc_align_static(16)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #146177 for more information = help: add `#![feature(static_align)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-thread_local.stderr b/tests/ui/feature-gates/feature-gate-thread_local.stderr index de6debafb9d02..36e508d156e72 100644 --- a/tests/ui/feature-gates/feature-gate-thread_local.stderr +++ b/tests/ui/feature-gates/feature-gate-thread_local.stderr @@ -1,8 +1,8 @@ error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors - --> $DIR/feature-gate-thread_local.rs:8:1 + --> $DIR/feature-gate-thread_local.rs:8:3 | LL | #[thread_local] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: see issue #29594 for more information = help: add `#![feature(thread_local)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index fb05273b6ffc4..53e691b8a13c6 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items - --> $DIR/feature-gated-feature-in-macro-arg.rs:8:9 + --> $DIR/feature-gated-feature-in-macro-arg.rs:8:11 | LL | #[rustc_intrinsic] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index db56f22acfba6..b6135f1f63a86 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -1,13 +1,3 @@ -error[E0658]: use of an internal attribute - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:1 - | -LL | #![rustc_main] - | ^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable - = note: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable - = note: the `#[rustc_main]` attribute is used internally to specify test entry point function - error: `#[macro_export]` attribute cannot be used on crates --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:9:1 | @@ -16,6 +6,16 @@ LL | #![macro_export] | = help: `#[macro_export]` can only be applied to macro defs +error[E0658]: use of an internal attribute + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:4 + | +LL | #![rustc_main] + | ^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + = note: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable + = note: the `#[rustc_main]` attribute is used internally to specify test entry point function + error: `#[rustc_main]` attribute cannot be used on crates --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:1 | diff --git a/tests/ui/force-inlining/gate.stderr b/tests/ui/force-inlining/gate.stderr index 6c2df08b1a3f1..d14387508f019 100644 --- a/tests/ui/force-inlining/gate.stderr +++ b/tests/ui/force-inlining/gate.stderr @@ -1,18 +1,18 @@ error[E0658]: use of an internal attribute - --> $DIR/gate.rs:4:1 + --> $DIR/gate.rs:4:3 | LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_force_inline]` attribute is an internal implementation detail that will never be stable = note: `#[rustc_force_inline]` forces a free function to be inlined error[E0658]: use of an internal attribute - --> $DIR/gate.rs:11:1 + --> $DIR/gate.rs:11:3 | LL | #[rustc_force_inline = "the test requires it"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_force_inline]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr index 6711c77a11eb3..33224a4b61b68 100644 --- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr +++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items - --> $DIR/incorrect-read_via_copy-defn.rs:6:1 + --> $DIR/incorrect-read_via_copy-defn.rs:6:3 | LL | #[rustc_intrinsic] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/intrinsics/incorrect-transmute.stderr b/tests/ui/intrinsics/incorrect-transmute.stderr index 6145a11c4ae0f..1599235889aee 100644 --- a/tests/ui/intrinsics/incorrect-transmute.stderr +++ b/tests/ui/intrinsics/incorrect-transmute.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items - --> $DIR/incorrect-transmute.rs:6:1 + --> $DIR/incorrect-transmute.rs:6:3 | LL | #[rustc_intrinsic] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/lang-items/issue-83471.stderr b/tests/ui/lang-items/issue-83471.stderr index 1d5b1c4cd3ed7..01310b4b8a965 100644 --- a/tests/ui/lang-items/issue-83471.stderr +++ b/tests/ui/lang-items/issue-83471.stderr @@ -4,61 +4,61 @@ error[E0573]: expected type, found built-in attribute `export_name` LL | fn call(export_name); | ^^^^^^^^^^^ not a type +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/issue-83471.rs:24:13 + | +LL | fn call(export_name); + | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + = note: `#[warn(anonymous_parameters)]` (part of `#[warn(rust_2018_compatibility)]`) on by default + +error[E0718]: `fn` lang item must be applied to a trait with 1 generic argument + --> $DIR/issue-83471.rs:20:1 + | +LL | #[lang = "fn"] + | ^^^^^^^^^^^^^^ +... +LL | trait Fn { + | - this trait has 0 generic arguments + error[E0658]: lang items are subject to change - --> $DIR/issue-83471.rs:8:1 + --> $DIR/issue-83471.rs:8:3 | LL | #[lang = "pointee_sized"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(lang_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: lang items are subject to change - --> $DIR/issue-83471.rs:12:1 + --> $DIR/issue-83471.rs:12:3 | LL | #[lang = "meta_sized"] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(lang_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: lang items are subject to change - --> $DIR/issue-83471.rs:16:1 + --> $DIR/issue-83471.rs:16:3 | LL | #[lang = "sized"] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: add `#![feature(lang_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: lang items are subject to change - --> $DIR/issue-83471.rs:20:1 + --> $DIR/issue-83471.rs:20:3 | LL | #[lang = "fn"] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = help: add `#![feature(lang_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/issue-83471.rs:24:13 - | -LL | fn call(export_name); - | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name` - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! - = note: for more information, see - = note: `#[warn(anonymous_parameters)]` (part of `#[warn(rust_2018_compatibility)]`) on by default - -error[E0718]: `fn` lang item must be applied to a trait with 1 generic argument - --> $DIR/issue-83471.rs:20:1 - | -LL | #[lang = "fn"] - | ^^^^^^^^^^^^^^ -... -LL | trait Fn { - | - this trait has 0 generic arguments - error[E0425]: cannot find function `a` in this scope --> $DIR/issue-83471.rs:30:5 | diff --git a/tests/ui/linkage-attr/linkage4.stderr b/tests/ui/linkage-attr/linkage4.stderr index 8fbcaf841b663..9e24b346356dc 100644 --- a/tests/ui/linkage-attr/linkage4.stderr +++ b/tests/ui/linkage-attr/linkage4.stderr @@ -1,8 +1,8 @@ error[E0658]: the `linkage` attribute is experimental and not portable across platforms - --> $DIR/linkage4.rs:1:1 + --> $DIR/linkage4.rs:1:3 | LL | #[linkage = "external"] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29603 for more information = help: add `#![feature(linkage)]` to the crate attributes to enable diff --git a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr index e28ff2ec70340..4efcd761571da 100644 --- a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr +++ b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[must_not_suspend]` attribute is an experimental feature - --> $DIR/feature-gate-must_not_suspend.rs:3:1 + --> $DIR/feature-gate-must_not_suspend.rs:3:3 | LL | #[must_not_suspend = "You gotta use Umm's, ya know?"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #83310 for more information = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable diff --git a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr index c6680666ece05..fa134c92dce84 100644 --- a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr +++ b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/feature-gate-on-unimplemented.rs:3:1 + --> $DIR/feature-gate-on-unimplemented.rs:3:3 | LL | #[rustc_on_unimplemented(label = "test error `{Self}` with `{Bar}`")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_on_unimplemented]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/panic-runtime/needs-gate.stderr b/tests/ui/panic-runtime/needs-gate.stderr index 9f66f05bac98b..e7407a22110b1 100644 --- a/tests/ui/panic-runtime/needs-gate.stderr +++ b/tests/ui/panic-runtime/needs-gate.stderr @@ -1,18 +1,18 @@ error[E0658]: the `#[panic_runtime]` attribute is an experimental feature - --> $DIR/needs-gate.rs:4:1 + --> $DIR/needs-gate.rs:4:4 | LL | #![panic_runtime] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: see issue #32837 for more information = help: add `#![feature(panic_runtime)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[needs_panic_runtime]` attribute is an experimental feature - --> $DIR/needs-gate.rs:5:1 + --> $DIR/needs-gate.rs:5:4 | LL | #![needs_panic_runtime] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #32837 for more information = help: add `#![feature(needs_panic_runtime)]` to the crate attributes to enable diff --git a/tests/ui/pin-ergonomics/pattern-matching.normal.stderr b/tests/ui/pin-ergonomics/pattern-matching.normal.stderr index 409013c34024a..e726fa970ed62 100644 --- a/tests/ui/pin-ergonomics/pattern-matching.normal.stderr +++ b/tests/ui/pin-ergonomics/pattern-matching.normal.stderr @@ -1,18 +1,18 @@ error[E0658]: the `#[pin_v2]` attribute is an experimental feature - --> $DIR/pattern-matching.rs:12:1 + --> $DIR/pattern-matching.rs:12:3 | LL | #[pin_v2] - | ^^^^^^^^^ + | ^^^^^^ | = note: see issue #130494 for more information = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[pin_v2]` attribute is an experimental feature - --> $DIR/pattern-matching.rs:18:1 + --> $DIR/pattern-matching.rs:18:3 | LL | #[pin_v2] - | ^^^^^^^^^ + | ^^^^^^ | = note: see issue #130494 for more information = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable diff --git a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr index 0b1af78b50410..53c88ae131346 100644 --- a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr +++ b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/feature-gate-doc_primitive.rs:1:1 + --> $DIR/feature-gate-doc_primitive.rs:1:3 | LL | #[rustc_doc_primitive = "usize"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_doc_primitive]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/thread-local/no-unstable.rs b/tests/ui/thread-local/no-unstable.rs index 3de7985e62dbd..6e94a6f5456f4 100644 --- a/tests/ui/thread-local/no-unstable.rs +++ b/tests/ui/thread-local/no-unstable.rs @@ -1,13 +1,12 @@ thread_local! { - //~^ ERROR: use of an internal attribute [E0658] - //~| ERROR: use of an internal attribute [E0658] - //~| ERROR: `#[used(linker)]` is currently unstable [E0658] + //~^ ERROR: `#[used(linker)]` is currently unstable [E0658] //~| ERROR: `#[used]` attribute cannot be used on constants - #[rustc_dummy = 17] + //~^ ERROR: use of an internal attribute [E0658] pub static FOO: () = (); #[cfg_attr(true, rustc_dummy = 17)] + //~^ ERROR: use of an internal attribute [E0658] pub static BAR: () = (); #[used(linker)] diff --git a/tests/ui/thread-local/no-unstable.stderr b/tests/ui/thread-local/no-unstable.stderr index 438020d00b7dd..0072e4c0eebb0 100644 --- a/tests/ui/thread-local/no-unstable.stderr +++ b/tests/ui/thread-local/no-unstable.stderr @@ -1,24 +1,18 @@ error[E0658]: use of an internal attribute - --> $DIR/no-unstable.rs:1:1 + --> $DIR/no-unstable.rs:4:7 | -LL | / thread_local! { -... | -LL | | pub static BAZ: () = (); -LL | | } - | |_^ +LL | #[rustc_dummy = 17] + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_dummy]` attribute is an internal implementation detail that will never be stable = note: the `#[rustc_dummy]` attribute is used for rustc unit tests error[E0658]: use of an internal attribute - --> $DIR/no-unstable.rs:1:1 + --> $DIR/no-unstable.rs:8:22 | -LL | / thread_local! { -... | -LL | | pub static BAZ: () = (); -LL | | } - | |_^ +LL | #[cfg_attr(true, rustc_dummy = 17)] + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_dummy]` attribute is an internal implementation detail that will never be stable @@ -28,6 +22,9 @@ error[E0658]: `#[used(linker)]` is currently unstable --> $DIR/no-unstable.rs:1:1 | LL | / thread_local! { +LL | | +LL | | +LL | | #[rustc_dummy = 17] ... | LL | | pub static BAZ: () = (); LL | | } @@ -41,6 +38,9 @@ error: `#[used]` attribute cannot be used on constants --> $DIR/no-unstable.rs:1:1 | LL | / thread_local! { +LL | | +LL | | +LL | | #[rustc_dummy = 17] ... | LL | | pub static BAZ: () = (); LL | | } diff --git a/tests/ui/tool-attributes/diagnostic_item.stderr b/tests/ui/tool-attributes/diagnostic_item.stderr index d37044281a136..4282c41621199 100644 --- a/tests/ui/tool-attributes/diagnostic_item.stderr +++ b/tests/ui/tool-attributes/diagnostic_item.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/diagnostic_item.rs:1:1 + --> $DIR/diagnostic_item.rs:1:3 | LL | #[rustc_diagnostic_item = "foomp"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types from the standard library for diagnostic purposes diff --git a/tests/ui/traits/const-traits/partial/attr-gate.stderr b/tests/ui/traits/const-traits/partial/attr-gate.stderr index e46e35d036bed..a6178646c52a9 100644 --- a/tests/ui/traits/const-traits/partial/attr-gate.stderr +++ b/tests/ui/traits/const-traits/partial/attr-gate.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/attr-gate.rs:2:5 + --> $DIR/attr-gate.rs:2:7 | LL | #[rustc_non_const_trait_method] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_non_const_trait_method]` attribute is an internal implementation detail that will never be stable diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr index 4d44ceff98a4e..29f0d499536f0 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr @@ -1,8 +1,8 @@ error[E0658]: use of an internal attribute - --> $DIR/rustc_must_implement_one_of_gated.rs:1:1 + --> $DIR/rustc_must_implement_one_of_gated.rs:1:3 | LL | #[rustc_must_implement_one_of(eq, neq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_must_implement_one_of]` attribute is an internal implementation detail that will never be stable From e994903b68b791a3f0a56642dbdf8d036c06a978 Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Fri, 10 Apr 2026 16:37:11 +0200 Subject: [PATCH 3/3] remove parser for `#[pointee]` as it is actually an unstable std lib proc macro --- .../src/attributes/traits.rs | 10 +------ compiler/rustc_attr_parsing/src/context.rs | 1 - .../feature-gate-derive-coerce-pointee.stderr | 29 ++----------------- 3 files changed, 3 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 09eeaf83856b4..f51e3c01aaa83 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -4,8 +4,8 @@ use super::prelude::*; use crate::attributes::{NoArgsAttributeParser, OnDuplicate, SingleAttributeParser}; use crate::context::{AcceptContext, Stage}; use crate::parser::ArgParser; +use crate::target_checking::AllowedTargets; use crate::target_checking::Policy::{Allow, Warn}; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; pub(crate) struct RustcSkipDuringMethodDispatchParser; impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { @@ -177,11 +177,3 @@ impl NoArgsAttributeParser for FundamentalParser { AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental; } - -pub(crate) struct PointeeParser; -impl NoArgsAttributeParser for PointeeParser { - const PATH: &[Symbol] = &[sym::pointee]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` - const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee; -} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 616a1dbf6a203..4af36dc52784d 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -273,7 +273,6 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, Single>, Single>, Single>, diff --git a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr index 2f7bd4f6f3d9a..19babe149d9a4 100644 --- a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr +++ b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr @@ -8,30 +8,6 @@ LL | #[derive(CoercePointee)] = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0659]: `pointee` is ambiguous - --> $DIR/feature-gate-derive-coerce-pointee.rs:5:24 - | -LL | struct MyPointer<'a, #[pointee] T: ?Sized> { - | ^^^^^^^ ambiguous name - | - = note: ambiguous because of a name conflict with a builtin attribute - = note: `pointee` could refer to a built-in attribute -note: `pointee` could also refer to the derive helper attribute defined here - --> $DIR/feature-gate-derive-coerce-pointee.rs:3:10 - | -LL | #[derive(CoercePointee)] - | ^^^^^^^^^^^^^ - -error[E0658]: the `#[pointee]` attribute is an experimental feature - --> $DIR/feature-gate-derive-coerce-pointee.rs:5:24 - | -LL | struct MyPointer<'a, #[pointee] T: ?Sized> { - | ^^^^^^^ - | - = note: see issue #123430 for more information - = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: use of unstable library feature `derive_coerce_pointee` --> $DIR/feature-gate-derive-coerce-pointee.rs:1:5 | @@ -42,7 +18,6 @@ LL | use std::marker::CoercePointee; = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0659. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`.