diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index b5934f4e36e89..323acebc1bdec 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -250,6 +250,15 @@ pub enum AttributeKind { span: Span, }, + /// Represents `#[export_stable]`. + ExportStable, + + /// Represents `#[ffi_const]`. + FfiConst(Span), + + /// Represents `#[ffi_pure]`. + FfiPure(Span), + /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), @@ -318,6 +327,9 @@ pub enum AttributeKind { span: Span, }, + /// Represents `#[rustc_std_internal_symbol]`. + StdInternalSymbol(Span), + /// Represents `#[target_feature(enable = "...")]` TargetFeature(ThinVec<(Symbol, Span)>, Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 02e95ddcb6fdb..a01537b356e4c 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -26,6 +26,9 @@ impl AttributeKind { Deprecation { .. } => Yes, DocComment { .. } => Yes, ExportName { .. } => Yes, + ExportStable => No, + FfiConst(..) => No, + FfiPure(..) => No, Inline(..) => No, LinkName { .. } => Yes, LinkSection { .. } => No, @@ -46,6 +49,7 @@ impl AttributeKind { RustcObjectLifetimeDefault => No, SkipDuringMethodDispatch { .. } => No, Stability { .. } => Yes, + StdInternalSymbol(..) => No, TargetFeature(..) => No, TrackCaller(..) => Yes, Used { .. } => No, diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index e298053ab7691..1a66eec870f25 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,9 +1,11 @@ use rustc_attr_data_structures::AttributeKind; use rustc_attr_data_structures::AttributeKind::{LinkName, LinkSection}; use rustc_feature::{AttributeTemplate, template}; -use rustc_span::{Symbol, sym}; +use rustc_span::{Span, Symbol, sym}; -use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::attributes::{ + AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, +}; use crate::context::{AcceptContext, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics::NullOnLinkSection; @@ -57,3 +59,31 @@ impl SingleAttributeParser for LinkSectionParser { Some(LinkSection { name, span: cx.attr_span }) } } + +pub(crate) struct ExportStableParser; +impl NoArgsAttributeParser for ExportStableParser { + const PATH: &[Symbol] = &[sym::export_stable]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable; +} + +pub(crate) struct FfiConstParser; +impl NoArgsAttributeParser for FfiConstParser { + const PATH: &[Symbol] = &[sym::ffi_const]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst; +} + +pub(crate) struct FfiPureParser; +impl NoArgsAttributeParser for FfiPureParser { + const PATH: &[Symbol] = &[sym::ffi_pure]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; +} + +pub(crate) struct StdInternalSymbolParser; +impl NoArgsAttributeParser for StdInternalSymbolParser { + const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 265e1bb6a8cba..9a6d2da3cfa5b 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -22,7 +22,10 @@ use crate::attributes::codegen_attrs::{ use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; -use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser}; +use crate::attributes::link_attrs::{ + ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkSectionParser, + StdInternalSymbolParser, +}; use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser}; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; use crate::attributes::must_use::MustUseParser; @@ -141,6 +144,9 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, + Single>, + Single>, Single>, Single>, Single>, @@ -148,6 +154,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 2713ec07f9759..173cbe70d1b25 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -211,6 +211,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER, UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER, }, + AttributeKind::FfiConst(_) => { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST + } + AttributeKind::FfiPure(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, + AttributeKind::StdInternalSymbol(_) => { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL + } _ => {} } } @@ -221,17 +228,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { match name { sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR, - sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, - sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND, sym::rustc_reallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR, sym::rustc_deallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR, sym::rustc_allocator_zeroed => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } - sym::rustc_std_internal_symbol => { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL - } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::linkage => { if let Some(val) = attr.value_str() { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 27355a422d1fe..87763607d0108 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -286,6 +286,9 @@ fn emit_malformed_attribute( if matches!( name, sym::inline + | sym::export_stable + | sym::ffi_const + | sym::ffi_pure | sym::may_dangle | sym::rustc_as_ptr | sym::rustc_pub_transparent diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c5ced4064140e..01d6d04525d28 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -201,6 +201,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span) | AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span), ) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target), + Attribute::Parsed(AttributeKind::ExportStable) => { + // handled in `check_export` + } + &Attribute::Parsed(AttributeKind::FfiConst(attr_span)) => { + self.check_ffi_const(attr_span, target) + } + &Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => { + self.check_ffi_pure(attr_span, attrs, target) + } Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect @@ -227,6 +236,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => { self.check_pass_by_value(attr_span, span, target) } + &Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => { + self.check_rustc_std_internal_symbol(attr_span, span, target) + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -252,9 +264,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ), [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target), - [sym::rustc_std_internal_symbol, ..] => { - self.check_rustc_std_internal_symbol(attr, span, target) - } [sym::rustc_no_implicit_autorefs, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } @@ -294,8 +303,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } - [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target), - [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::macro_use, ..] | [sym::macro_escape, ..] => { @@ -340,7 +347,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfg_attr | sym::cfg_trace | sym::cfg_attr_trace - | sym::export_stable // handled in `check_export` // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) | sym::pointee // FIXME(derive_coerce_pointee) @@ -1501,7 +1507,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span }); return; } - if attrs.iter().any(|a| a.has_name(sym::ffi_const)) { + if find_attr!(attrs, AttributeKind::FfiConst(_)) { // `#[ffi_const]` functions cannot be `#[ffi_pure]` self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span }); } @@ -2212,13 +2218,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) { + fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) { match target { Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {} _ => { - self.tcx - .dcx() - .emit_err(errors::RustcStdInternalSymbol { attr_span: attr.span(), span }); + self.tcx.dcx().emit_err(errors::RustcStdInternalSymbol { attr_span, span }); } } } diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index f8f489d7d0673..b1f4584c2a88a 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -2,6 +2,7 @@ use std::iter; use std::ops::ControlFlow; use rustc_abi::ExternAbi; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -14,7 +15,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Visibility, }; use rustc_session::config::CrateType; -use rustc_span::{Span, sym}; +use rustc_span::Span; use crate::errors::UnexportableItem; @@ -44,7 +45,7 @@ impl<'tcx> ExportableItemCollector<'tcx> { } fn item_is_exportable(&self, def_id: LocalDefId) -> bool { - let has_attr = self.tcx.has_attr(def_id, sym::export_stable); + let has_attr = find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::ExportStable); if !self.in_exportable_mod && !has_attr { return false; } @@ -80,7 +81,7 @@ impl<'tcx> ExportableItemCollector<'tcx> { fn walk_item_with_mod(&mut self, item: &'tcx hir::Item<'tcx>) { let def_id = item.hir_id().owner.def_id; let old_exportable_mod = self.in_exportable_mod; - if self.tcx.get_attr(def_id, sym::export_stable).is_some() { + if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::ExportStable) { self.in_exportable_mod = true; } let old_seen_exportable_in_mod = std::mem::replace(&mut self.seen_exportable_in_mod, false); diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 32b0ddf87ba4f..ed7d5a263b11a 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -40,12 +40,6 @@ error: malformed `crate_name` attribute input LL | #[crate_name] | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` -error: malformed `export_stable` attribute input - --> $DIR/malformed-attrs.rs:80:1 - | -LL | #[export_stable = 1] - | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_stable]` - error: malformed `coverage` attribute input --> $DIR/malformed-attrs.rs:89:1 | @@ -140,24 +134,12 @@ error: malformed `fundamental` attribute input LL | #[fundamental()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[fundamental]` -error: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:164:5 - | -LL | #[unsafe(ffi_pure = 1)] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[ffi_pure]` - error: malformed `link_ordinal` attribute input --> $DIR/malformed-attrs.rs:166:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_ordinal(ordinal)]` -error: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:170:5 - | -LL | #[unsafe(ffi_const = 1)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[ffi_const]` - error: malformed `linkage` attribute input --> $DIR/malformed-attrs.rs:172:5 | @@ -490,6 +472,15 @@ LL | #[target_feature] | expected this to be a list | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` +error[E0565]: malformed `export_stable` attribute input + --> $DIR/malformed-attrs.rs:80:1 + | +LL | #[export_stable = 1] + | ^^^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[export_stable]` + error[E0539]: malformed `link_name` attribute input --> $DIR/malformed-attrs.rs:85:1 | @@ -546,6 +537,24 @@ LL | #[rustc_layout_scalar_valid_range_end] | expected this to be a list | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error[E0565]: malformed `ffi_pure` attribute input + --> $DIR/malformed-attrs.rs:164:5 + | +LL | #[unsafe(ffi_pure = 1)] + | ^^^^^^^^^^^^^^^^^^---^^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[ffi_pure]` + +error[E0565]: malformed `ffi_const` attribute input + --> $DIR/malformed-attrs.rs:170:5 + | +LL | #[unsafe(ffi_const = 1)] + | ^^^^^^^^^^^^^^^^^^^---^^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[ffi_const]` + error[E0565]: malformed `non_exhaustive` attribute input --> $DIR/malformed-attrs.rs:196:1 |