Auto merge of #151382 - JonathanBrouwer:attr-perf, r=jdonszelmann
Only run finalizers of accepted attributes Locally this had insanely good perf, but lets see what reality thinks about this r? @jdonszelmann Attribute parsing consists of two stages: - All attribute are "accepted" by one or more parsers, which means the unparsed attribute is parsed, information about it is stored in the attr parser struct - After all attributes are parsed, we "finalize" all parsers, producing a single parsed attribute representation from the parser struct. This two-stage process exist so multiple attributes can get merged into one parser representation. For example if you have two repr attributes `#[repr(C)]` `#[repr(packed)]` it will only produce one parsed `Repr` attribue. The dumb thing we did was we would "finalize" all parsers, even the ones that never accepted an attribute. This PR only calls finalize on the parsers that accepted at least one attribute.
This commit is contained in:
commit
d276646872
6 changed files with 49 additions and 47 deletions
|
|
@ -103,18 +103,18 @@ type GroupType<S> = LazyLock<GroupTypeInner<S>>;
|
|||
|
||||
pub(super) struct GroupTypeInner<S: Stage> {
|
||||
pub(super) accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
|
||||
pub(super) finalizers: Vec<FinalizeFn<S>>,
|
||||
}
|
||||
|
||||
pub(super) struct GroupTypeInnerAccept<S: Stage> {
|
||||
pub(super) template: AttributeTemplate,
|
||||
pub(super) accept_fn: AcceptFn<S>,
|
||||
pub(super) allowed_targets: AllowedTargets,
|
||||
pub(super) finalizer: FinalizeFn<S>,
|
||||
}
|
||||
|
||||
type AcceptFn<S> =
|
||||
pub(crate) type AcceptFn<S> =
|
||||
Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser) + Send + Sync>;
|
||||
type FinalizeFn<S> =
|
||||
pub(crate) type FinalizeFn<S> =
|
||||
Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
|
||||
|
||||
macro_rules! attribute_parsers {
|
||||
|
|
@ -142,8 +142,7 @@ macro_rules! attribute_parsers {
|
|||
@[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
|
||||
) => {
|
||||
pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
|
||||
let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
|
||||
let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
|
||||
let mut accepters = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
|
||||
$(
|
||||
{
|
||||
thread_local! {
|
||||
|
|
@ -151,7 +150,7 @@ macro_rules! attribute_parsers {
|
|||
};
|
||||
|
||||
for (path, template, accept_fn) in <$names>::ATTRIBUTES {
|
||||
accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
|
||||
accepters.entry(*path).or_default().push(GroupTypeInnerAccept {
|
||||
template: *template,
|
||||
accept_fn: Box::new(|cx, args| {
|
||||
STATE_OBJECT.with_borrow_mut(|s| {
|
||||
|
|
@ -159,17 +158,16 @@ macro_rules! attribute_parsers {
|
|||
})
|
||||
}),
|
||||
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
|
||||
finalizer: Box::new(|cx| {
|
||||
let state = STATE_OBJECT.take();
|
||||
state.finalize(cx)
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
finalizes.push(Box::new(|cx| {
|
||||
let state = STATE_OBJECT.take();
|
||||
state.finalize(cx)
|
||||
}));
|
||||
}
|
||||
)*
|
||||
|
||||
GroupTypeInner { accepters:accepts, finalizers:finalizes }
|
||||
GroupTypeInner { accepters }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_session::Session;
|
|||
use rustc_session::lint::{BuiltinLintDiag, LintId};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
|
||||
use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
|
||||
use crate::context::{AcceptContext, FinalizeContext, FinalizeFn, SharedContext, Stage};
|
||||
use crate::early_parsed::{EARLY_PARSED_ATTRIBUTES, EarlyParsedState};
|
||||
use crate::parser::{ArgParser, PathParser, RefPathParser};
|
||||
use crate::session_diagnostics::ParsedDescription;
|
||||
|
|
@ -270,6 +270,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
|
||||
let mut early_parsed_state = EarlyParsedState::default();
|
||||
|
||||
let mut finalizers: Vec<&FinalizeFn<S>> = Vec::with_capacity(attrs.len());
|
||||
|
||||
for attr in attrs {
|
||||
// If we're only looking for a single attribute, skip all the ones we don't care about.
|
||||
if let Some(expected) = self.parse_only {
|
||||
|
|
@ -383,6 +385,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
};
|
||||
|
||||
(accept.accept_fn)(&mut cx, &args);
|
||||
finalizers.push(&accept.finalizer);
|
||||
|
||||
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
|
||||
Self::check_target(&accept.allowed_targets, target, &mut cx);
|
||||
}
|
||||
|
|
@ -417,7 +421,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
}
|
||||
|
||||
early_parsed_state.finalize_early_parsed_attributes(&mut attributes);
|
||||
for f in &S::parsers().finalizers {
|
||||
for f in &finalizers {
|
||||
if let Some(attr) = f(&mut FinalizeContext {
|
||||
shared: SharedContext { cx: self, target_span, target, emit_lint: &mut emit_lint },
|
||||
all_attrs: &attr_paths,
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ mod to_reuse {
|
|||
#[attr = Cold]
|
||||
fn foo_no_reason(x: usize) -> usize { x }
|
||||
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Cold]
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
fn bar(x: usize) -> usize { x }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@ impl Trait for S {
|
|||
fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) }
|
||||
|
||||
// Check that #[inline(hint)] is added when other attributes present in inner reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
#[attr = MustUse]
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
|
||||
|
|
@ -59,18 +59,18 @@ impl Trait for S {
|
|||
fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
|
||||
// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Inline(Never)]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
#[attr = MustUse]
|
||||
#[attr = Inline(Never)]
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
}.foo()
|
||||
}
|
||||
|
||||
// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
#[attr = MustUse]
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo1(self: _) -> _ { self.0.foo1() }
|
||||
|
||||
|
|
@ -83,10 +83,10 @@ impl Trait for S {
|
|||
fn foo3(self: _) -> _ { self.0.foo3() }
|
||||
|
||||
// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Inline(Never)]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
#[attr = MustUse]
|
||||
#[attr = Inline(Never)]
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
fn foo4(self: _) -> _ { self.0.foo4() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,3 @@
|
|||
error: can't mark as unstable using an already stable feature
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
|
||||
LL | const fn my_fun() {}
|
||||
| -------------------- the stability attribute annotates this item
|
||||
|
|
||||
help: consider removing the attribute
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: can't mark as unstable using an already stable feature
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
|
||||
|
|
||||
|
|
@ -27,5 +13,19 @@ help: consider removing the attribute
|
|||
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: can't mark as unstable using an already stable feature
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
|
||||
LL | const fn my_fun() {}
|
||||
| -------------------- the stability attribute annotates this item
|
||||
|
|
||||
help: consider removing the attribute
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -94,14 +94,6 @@ LL | #[const_continue]
|
|||
|
|
||||
= help: `#[const_continue]` can be applied to
|
||||
|
||||
error: `#[const_continue]` should be applied to a break expression
|
||||
--> $DIR/invalid-attribute.rs:40:9
|
||||
|
|
||||
LL | #[const_continue]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
LL | 5
|
||||
| - not a break expression
|
||||
|
||||
error: `#[loop_match]` should be applied to a loop
|
||||
--> $DIR/invalid-attribute.rs:39:9
|
||||
|
|
||||
|
|
@ -111,5 +103,13 @@ LL | #[const_continue]
|
|||
LL | 5
|
||||
| - not a loop
|
||||
|
||||
error: `#[const_continue]` should be applied to a break expression
|
||||
--> $DIR/invalid-attribute.rs:40:9
|
||||
|
|
||||
LL | #[const_continue]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
LL | 5
|
||||
| - not a break expression
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue