diff options
Diffstat (limited to 'compiler/rustc_attr_parsing/src/context.rs')
| -rw-r--r-- | compiler/rustc_attr_parsing/src/context.rs | 91 |
1 files changed, 55 insertions, 36 deletions
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 9b86d101840..80dfdffdb55 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -5,10 +5,10 @@ use std::sync::LazyLock; use private::Sealed; use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId}; -use rustc_attr_data_structures::AttributeKind; -use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind}; use rustc_errors::{DiagCtxtHandle, Diagnostic}; use rustc_feature::{AttributeTemplate, Features}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::lints::{AttributeLint, AttributeLintKind}; use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId}; use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; @@ -16,10 +16,10 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{ AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser, }; +use crate::attributes::body::CoroutineParser; use crate::attributes::codegen_attrs::{ - ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, - OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, - UsedParser, + ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, + TargetFeatureParser, TrackCallerParser, UsedParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -50,7 +50,7 @@ use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; -use crate::attributes::test_attrs::IgnoreParser; +use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser}; use crate::attributes::traits::{ AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, @@ -62,15 +62,23 @@ use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, MetaItemParser, PathParser}; use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; -macro_rules! group_type { - ($stage: ty) => { - LazyLock<( - BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>, - Vec<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $stage>) -> Option<AttributeKind>>> - )> - }; +type GroupType<S> = LazyLock<GroupTypeInner<S>>; + +struct GroupTypeInner<S: Stage> { + accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>, + finalizers: Vec<FinalizeFn<S>>, +} + +struct GroupTypeInnerAccept<S: Stage> { + template: AttributeTemplate, + accept_fn: AcceptFn<S>, } +type AcceptFn<S> = + Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>; +type FinalizeFn<S> = + Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>; + macro_rules! attribute_parsers { ( pub(crate) static $name: ident = [$($names: ty),* $(,)?]; @@ -93,11 +101,11 @@ macro_rules! attribute_parsers { } }; ( - @[$ty: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?]; + @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?]; ) => { - pub(crate) static $name: group_type!($ty) = LazyLock::new(|| { - let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new(); - let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $ty>) -> Option<AttributeKind>>>::new(); + pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| { + let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new(); + let mut finalizes = Vec::<FinalizeFn<$stage>>::new(); $( { thread_local! { @@ -105,11 +113,14 @@ macro_rules! attribute_parsers { }; for (path, template, accept_fn) in <$names>::ATTRIBUTES { - accepts.entry(*path).or_default().push((*template, Box::new(|cx, args| { - STATE_OBJECT.with_borrow_mut(|s| { - accept_fn(s, cx, args) + accepts.entry(*path).or_default().push(GroupTypeInnerAccept { + template: *template, + accept_fn: Box::new(|cx, args| { + STATE_OBJECT.with_borrow_mut(|s| { + accept_fn(s, cx, args) + }) }) - }))); + }); } finalizes.push(Box::new(|cx| { @@ -119,7 +130,7 @@ macro_rules! attribute_parsers { } )* - (accepts, finalizes) + GroupTypeInner { accepters:accepts, finalizers:finalizes } }); }; } @@ -163,6 +174,7 @@ attribute_parsers!( Single<RustcLayoutScalarValidRangeEnd>, Single<RustcLayoutScalarValidRangeStart>, Single<RustcObjectLifetimeDefaultParser>, + Single<ShouldPanicParser>, Single<SkipDuringMethodDispatchParser>, Single<TransparencyParser>, Single<WithoutArgs<AllowIncoherentImplParser>>, @@ -174,6 +186,7 @@ attribute_parsers!( Single<WithoutArgs<ConstContinueParser>>, Single<WithoutArgs<ConstStabilityIndirectParser>>, Single<WithoutArgs<ConstTraitParser>>, + Single<WithoutArgs<CoroutineParser>>, Single<WithoutArgs<DenyExplicitImplParser>>, Single<WithoutArgs<DoNotImplementViaObjectParser>>, Single<WithoutArgs<ExportStableParser>>, @@ -187,7 +200,6 @@ attribute_parsers!( Single<WithoutArgs<NoImplicitPreludeParser>>, Single<WithoutArgs<NoMangleParser>>, Single<WithoutArgs<NonExhaustiveParser>>, - Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>, Single<WithoutArgs<ParenSugarParser>>, Single<WithoutArgs<PassByValueParser>>, Single<WithoutArgs<PointeeParser>>, @@ -213,24 +225,24 @@ mod private { #[allow(private_interfaces)] pub trait Stage: Sized + 'static + Sealed { type Id: Copy; - const SHOULD_EMIT_LINTS: bool; - fn parsers() -> &'static group_type!(Self); + fn parsers() -> &'static GroupType<Self>; fn emit_err<'sess>( &self, sess: &'sess Session, diag: impl for<'x> Diagnostic<'x>, ) -> ErrorGuaranteed; + + fn should_emit(&self) -> ShouldEmit; } // allow because it's a sealed trait #[allow(private_interfaces)] impl Stage for Early { type Id = NodeId; - const SHOULD_EMIT_LINTS: bool = false; - fn parsers() -> &'static group_type!(Self) { + fn parsers() -> &'static GroupType<Self> { &early::ATTRIBUTE_PARSERS } fn emit_err<'sess>( @@ -244,15 +256,18 @@ impl Stage for Early { sess.dcx().create_err(diag).delay_as_bug() } } + + fn should_emit(&self) -> ShouldEmit { + self.emit_errors + } } // allow because it's a sealed trait #[allow(private_interfaces)] impl Stage for Late { type Id = HirId; - const SHOULD_EMIT_LINTS: bool = true; - fn parsers() -> &'static group_type!(Self) { + fn parsers() -> &'static GroupType<Self> { &late::ATTRIBUTE_PARSERS } fn emit_err<'sess>( @@ -262,6 +277,10 @@ impl Stage for Late { ) -> ErrorGuaranteed { tcx.dcx().emit_err(diag) } + + fn should_emit(&self) -> ShouldEmit { + ShouldEmit::ErrorsAndLints + } } /// used when parsing attributes for miscellaneous things *before* ast lowering @@ -300,7 +319,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { /// must be delayed until after HIR is built. This method will take care of the details of /// that. pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) { - if !S::SHOULD_EMIT_LINTS { + if !self.stage.should_emit().should_emit() { return; } let id = self.target_id; @@ -811,8 +830,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let args = parser.args(); let parts = path.segments().map(|i| i.name).collect::<Vec<_>>(); - if let Some(accepts) = S::parsers().0.get(parts.as_slice()) { - for (template, accept) in accepts { + if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) { + for accept in accepts { let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { shared: SharedContext { cx: self, @@ -821,11 +840,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { emit_lint: &mut emit_lint, }, attr_span: lower_span(attr.span), - template, + template: &accept.template, attr_path: path.get_attribute_path(), }; - accept(&mut cx, args) + (accept.accept_fn)(&mut cx, args) } } else { // If we're here, we must be compiling a tool attribute... Or someone @@ -856,7 +875,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { } let mut parsed_attributes = Vec::new(); - for f in &S::parsers().1 { + for f in &S::parsers().finalizers { if let Some(attr) = f(&mut FinalizeContext { shared: SharedContext { cx: self, @@ -877,7 +896,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { /// Returns whether there is a parser for an attribute with this name pub fn is_parsed_attribute(path: &[Symbol]) -> bool { - Late::parsers().0.contains_key(path) + Late::parsers().accepters.contains_key(path) } fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs { |
