mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Remove AttributeSafety from BUILTIN_ATTRIBUTES
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
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,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
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,
|
||||
|
||||
@@ -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 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::export_name];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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<S: Stage> AttributeParser<S> 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 @@ impl<S: Stage> NoArgsAttributeParser<S> for TrackCallerParser {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser {
|
||||
const PATH: &[Symbol] = &[sym::no_mangle];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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 @@ fn extend(
|
||||
impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
|
||||
type Item = (Symbol, Span);
|
||||
const PATH: &[Symbol] = &[sym::force_target_feature];
|
||||
const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None };
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature {
|
||||
features: items,
|
||||
attr_span: span,
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
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 @@ fn parse_link_import_name_type<S: Stage>(
|
||||
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
|
||||
const PATH: &[Symbol] = &[sym::link_section];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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 @@ impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
|
||||
const PATH: &[Symbol] = &[sym::ffi_const];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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 @@ impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
|
||||
const PATH: &[Symbol] = &[sym::ffi_pure];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
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<S: Stage>: Default + 'static {
|
||||
/// If an attribute has this symbol, the `accept` function will be called on it.
|
||||
const ATTRIBUTES: AcceptMapping<Self, S>;
|
||||
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<S: Stage>: 'static {
|
||||
/// Configures what to do when when the same attribute is
|
||||
/// applied more than once on the same syntax node.
|
||||
const ON_DUPLICATE: OnDuplicate<S>;
|
||||
const SAFETY: AttributeSafety = AttributeSafety::Normal;
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets;
|
||||
|
||||
@@ -165,6 +168,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
||||
},
|
||||
)];
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
const SAFETY: AttributeSafety = T::SAFETY;
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
Some(self.1?.0)
|
||||
@@ -217,6 +221,18 @@ fn exec<P: SingleAttributeParser<S>>(
|
||||
}
|
||||
}
|
||||
|
||||
#[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<Edition> },
|
||||
}
|
||||
|
||||
/// 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<S: Stage>: 'static {
|
||||
const PATH: &[Symbol];
|
||||
const ON_DUPLICATE: OnDuplicate<S>;
|
||||
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 @@ fn default() -> Self {
|
||||
impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
|
||||
const PATH: &[Symbol] = T::PATH;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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<S: Stage>: '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<Self::Item>;
|
||||
const SAFETY: AttributeSafety = AttributeSafety::Normal;
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets;
|
||||
|
||||
@@ -312,6 +331,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
|
||||
group.items.extend(T::extend(cx, args))
|
||||
})];
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
const SAFETY: AttributeSafety = T::SAFETY;
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if let Some(first_span) = self.first_span {
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
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<S: Stage> {
|
||||
pub(super) template: AttributeTemplate,
|
||||
pub(super) accept_fn: AcceptFn<S>,
|
||||
pub(super) allowed_targets: AllowedTargets,
|
||||
pub(super) safety: AttributeSafety,
|
||||
pub(super) finalizer: FinalizeFn<S>,
|
||||
}
|
||||
|
||||
@@ -126,6 +127,7 @@ mod late {
|
||||
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();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
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 @@ pub fn parse_single<T>(
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser) -> Option<T>,
|
||||
template: &AttributeTemplate,
|
||||
allow_expr_metavar: AllowExprMetavar,
|
||||
expected_safety: AttributeSafety,
|
||||
) -> Option<T> {
|
||||
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
|
||||
panic!("parse_single called on a doc attr")
|
||||
@@ -157,6 +159,7 @@ pub fn parse_single<T>(
|
||||
attr.style,
|
||||
path,
|
||||
Some(normal_attr.item.unsafety),
|
||||
expected_safety,
|
||||
ParsedDescription::Attribute,
|
||||
target_span,
|
||||
target_node_id,
|
||||
@@ -178,6 +181,7 @@ pub fn parse_single_args<T, I>(
|
||||
attr_style: AttrStyle,
|
||||
attr_path: AttrPath,
|
||||
attr_safety: Option<Safety>,
|
||||
expected_safety: AttributeSafety,
|
||||
parsed_description: ParsedDescription,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
@@ -199,7 +203,13 @@ pub fn parse_single_args<T, I>(
|
||||
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 @@ pub fn parse_attribute_list(
|
||||
}
|
||||
};
|
||||
|
||||
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::<Vec<_>>();
|
||||
|
||||
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 @@ pub fn parse_attribute_list(
|
||||
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
|
||||
{
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -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 @@ pub fn check_attribute_safety(
|
||||
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 @@ pub fn check_attribute_safety(
|
||||
|
||||
// - 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 @@ pub fn check_attribute_safety(
|
||||
|
||||
// - 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",
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
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<CfgEntry,
|
||||
AttrStyle::Inner,
|
||||
AttrPath { segments: vec![sym::cfg].into_boxed_slice(), span },
|
||||
None,
|
||||
AttributeSafety::Normal,
|
||||
ParsedDescription::Macro,
|
||||
span,
|
||||
cx.current_expansion.lint_node_id,
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
};
|
||||
use rustc_attr_parsing::parser::AllowExprMetavar;
|
||||
use rustc_attr_parsing::{
|
||||
self as attr, AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry,
|
||||
parse_cfg,
|
||||
self as attr, AttributeParser, AttributeSafety, CFG_TEMPLATE, EvalConfigResult, ShouldEmit,
|
||||
eval_config_entry, parse_cfg,
|
||||
};
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_errors::msg;
|
||||
@@ -398,6 +398,7 @@ pub(crate) fn cfg_true(&self, attr: &Attribute, emit_errors: ShouldEmit) -> Eval
|
||||
parse_cfg,
|
||||
&CFG_TEMPLATE,
|
||||
AllowExprMetavar::Yes,
|
||||
AttributeSafety::Normal,
|
||||
) else {
|
||||
// Cfg attribute was not parsable, give up
|
||||
return EvalConfigResult::True;
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
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 @@ fn expand_cfg_true(
|
||||
parse_cfg,
|
||||
&CFG_TEMPLATE,
|
||||
AllowExprMetavar::Yes,
|
||||
AttributeSafety::Normal,
|
||||
) else {
|
||||
// Cfg attribute was not parsable, give up
|
||||
return EvalConfigResult::True;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
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<Edition> },
|
||||
}
|
||||
|
||||
#[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,
|
||||
}
|
||||
|
||||
@@ -348,10 +288,7 @@ pub struct BuiltinAttribute {
|
||||
ungated!(forbid),
|
||||
ungated!(deny),
|
||||
ungated!(must_use),
|
||||
gated!(
|
||||
must_not_suspend,
|
||||
experimental!(must_not_suspend)
|
||||
),
|
||||
gated!(must_not_suspend, experimental!(must_not_suspend)),
|
||||
ungated!(deprecated),
|
||||
|
||||
// Crate properties:
|
||||
@@ -366,222 +303,103 @@ pub struct BuiltinAttribute {
|
||||
// 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,
|
||||
),
|
||||
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,
|
||||
"types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs"
|
||||
),
|
||||
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"),
|
||||
|
||||
// Limits:
|
||||
ungated!(
|
||||
recursion_limit,
|
||||
),
|
||||
ungated!(
|
||||
type_length_limit,
|
||||
),
|
||||
gated!(
|
||||
move_size_limit,
|
||||
large_assignments, experimental!(move_size_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!(panic_handler), // RFC 2070
|
||||
|
||||
// Code generation:
|
||||
ungated!(
|
||||
inline,
|
||||
),
|
||||
ungated!(
|
||||
cold,
|
||||
),
|
||||
ungated!(
|
||||
no_builtins,
|
||||
),
|
||||
ungated!(
|
||||
target_feature,
|
||||
),
|
||||
ungated!(
|
||||
track_caller,
|
||||
),
|
||||
ungated!(
|
||||
instruction_set,
|
||||
),
|
||||
gated!(
|
||||
unsafe force_target_feature,
|
||||
effective_target_features, experimental!(force_target_feature)
|
||||
),
|
||||
gated!(
|
||||
sanitize,
|
||||
sanitize, experimental!(sanitize),
|
||||
),
|
||||
gated!(
|
||||
coverage,
|
||||
coverage_attribute, experimental!(coverage)
|
||||
),
|
||||
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!(sanitize, sanitize, experimental!(sanitize)),
|
||||
gated!(coverage, coverage_attribute, experimental!(coverage)),
|
||||
|
||||
ungated!(
|
||||
doc,
|
||||
),
|
||||
ungated!(doc),
|
||||
|
||||
// Debugging
|
||||
ungated!(
|
||||
debugger_visualizer,
|
||||
),
|
||||
ungated!(
|
||||
collapse_debuginfo,
|
||||
),
|
||||
ungated!(debugger_visualizer),
|
||||
ungated!(collapse_debuginfo),
|
||||
|
||||
// ==========================================================================
|
||||
// Unstable attributes:
|
||||
// ==========================================================================
|
||||
|
||||
// Linking:
|
||||
gated!(
|
||||
export_stable,
|
||||
experimental!(export_stable)
|
||||
),
|
||||
gated!(export_stable, experimental!(export_stable)),
|
||||
|
||||
// Testing:
|
||||
gated!(
|
||||
test_runner,
|
||||
custom_test_frameworks,
|
||||
"custom test frameworks are an unstable feature",
|
||||
),
|
||||
gated!(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",
|
||||
),
|
||||
gated!(reexport_test_harness_main, custom_test_frameworks, "custom test frameworks are an unstable feature"),
|
||||
|
||||
// RFC #1268
|
||||
gated!(
|
||||
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)
|
||||
),
|
||||
gated!(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!(
|
||||
optimize,
|
||||
optimize_attribute, experimental!(optimize)
|
||||
),
|
||||
gated!(optimize, optimize_attribute, experimental!(optimize)),
|
||||
|
||||
gated!(
|
||||
unsafe ffi_pure,
|
||||
experimental!(ffi_pure)
|
||||
),
|
||||
gated!(
|
||||
unsafe ffi_const,
|
||||
experimental!(ffi_const)
|
||||
),
|
||||
gated!(
|
||||
register_tool,
|
||||
experimental!(register_tool),
|
||||
),
|
||||
gated!(ffi_pure, experimental!(ffi_pure)),
|
||||
gated!(ffi_const, experimental!(ffi_const)),
|
||||
gated!(register_tool, experimental!(register_tool)),
|
||||
// `#[cfi_encoding = ""]`
|
||||
gated!(
|
||||
cfi_encoding,
|
||||
experimental!(cfi_encoding)
|
||||
),
|
||||
gated!(cfi_encoding, experimental!(cfi_encoding)),
|
||||
|
||||
// `#[coroutine]` attribute to be applied to closures to make them coroutines instead
|
||||
gated!(
|
||||
coroutine,
|
||||
coroutines, experimental!(coroutine)
|
||||
),
|
||||
gated!(coroutine, coroutines, experimental!(coroutine)),
|
||||
|
||||
// RFC 3543
|
||||
// `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
|
||||
gated!(
|
||||
patchable_function_entry,
|
||||
experimental!(patchable_function_entry)
|
||||
),
|
||||
gated!(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!(
|
||||
const_continue,
|
||||
loop_match, experimental!(const_continue)
|
||||
),
|
||||
gated!(
|
||||
loop_match,
|
||||
loop_match, experimental!(loop_match)
|
||||
),
|
||||
gated!(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!(
|
||||
pin_v2,
|
||||
pin_ergonomics, experimental!(pin_v2),
|
||||
),
|
||||
gated!(pin_v2, pin_ergonomics, experimental!(pin_v2)),
|
||||
|
||||
// ==========================================================================
|
||||
// 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),
|
||||
@@ -636,24 +454,12 @@ pub struct 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),
|
||||
@@ -720,49 +526,31 @@ pub struct 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,
|
||||
@@ -873,7 +661,6 @@ pub struct BuiltinAttribute {
|
||||
|
||||
BuiltinAttribute {
|
||||
name: sym::rustc_diagnostic_item,
|
||||
safety: AttributeSafety::Normal,
|
||||
gate: Gated {
|
||||
feature: sym::rustc_attrs,
|
||||
message: "use of an internal attribute",
|
||||
@@ -961,99 +748,39 @@ pub struct BuiltinAttribute {
|
||||
// ==========================================================================
|
||||
|
||||
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,
|
||||
),
|
||||
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_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 {
|
||||
|
||||
@@ -129,7 +129,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
|
||||
|
||||
pub use accepted::ACCEPTED_LANG_FEATURES;
|
||||
pub use builtin_attrs::{
|
||||
AttrSuggestionStyle, AttributeGate, AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP,
|
||||
AttrSuggestionStyle, AttributeGate, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP,
|
||||
BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, find_gated_cfg, is_builtin_attr_name,
|
||||
};
|
||||
pub use removed::REMOVED_LANG_FEATURES;
|
||||
|
||||
Reference in New Issue
Block a user