From 28eca4a8fe72ba498761e567ed92fa2a61c5e726 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 19 Jan 2026 21:50:15 +0100 Subject: [PATCH 1/2] Only run finalizers of accepted attributes --- compiler/rustc_attr_parsing/src/context.rs | 22 +++++++++----------- compiler/rustc_attr_parsing/src/interface.rs | 8 +++++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0c882fee01c8a..693ee0391171e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -103,18 +103,18 @@ type GroupType = LazyLock>; pub(super) struct GroupTypeInner { pub(super) accepters: BTreeMap<&'static [Symbol], Vec>>, - pub(super) finalizers: Vec>, } pub(super) struct GroupTypeInnerAccept { pub(super) template: AttributeTemplate, pub(super) accept_fn: AcceptFn, pub(super) allowed_targets: AllowedTargets, + pub(super) finalizer: FinalizeFn, } -type AcceptFn = +pub(crate) type AcceptFn = Box Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser) + Send + Sync>; -type FinalizeFn = +pub(crate) type FinalizeFn = Box) -> Option>; 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>>::new(); - let mut finalizes = Vec::>::new(); + let mut accepters = BTreeMap::<_, Vec>>::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 } }); }; } diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index c6be18321b5e3..bac4936c20d24 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -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> = Vec::new(); let mut early_parsed_state = EarlyParsedState::default(); + let mut finalizers: Vec<&FinalizeFn> = 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, From 6dc27bf7de8dd306baba6e6904fa5234bc56d9f1 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 19 Jan 2026 21:50:29 +0100 Subject: [PATCH 2/2] Update uitests --- tests/pretty/delegation-inherit-attributes.pp | 2 +- tests/pretty/delegation-inline-attribute.pp | 20 ++++++++--------- ...ute-rejects-already-stable-features.stderr | 22 +++++++++---------- tests/ui/loop-match/invalid-attribute.stderr | 16 +++++++------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/pretty/delegation-inherit-attributes.pp b/tests/pretty/delegation-inherit-attributes.pp index 2398cae90fdbf..9d51a80da7b98 100644 --- a/tests/pretty/delegation-inherit-attributes.pp +++ b/tests/pretty/delegation-inherit-attributes.pp @@ -21,8 +21,8 @@ #[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 } } diff --git a/tests/pretty/delegation-inline-attribute.pp b/tests/pretty/delegation-inline-attribute.pp index 5235fd8d0ef23..f83ae47b81f6c 100644 --- a/tests/pretty/delegation-inline-attribute.pp +++ b/tests/pretty/delegation-inline-attribute.pp @@ -44,9 +44,9 @@ 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 @@ 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 @@ 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() } } diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr index d599523c7274d..319056a9c8898 100644 --- a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr @@ -1,31 +1,31 @@ error: can't mark as unstable using an already stable feature - --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 | +LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable 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 + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 | -LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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:6:1 + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 | -LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable 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:6:1 + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 | -LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/loop-match/invalid-attribute.stderr b/tests/ui/loop-match/invalid-attribute.stderr index ddb68aea31b69..c23452b9b8448 100644 --- a/tests/ui/loop-match/invalid-attribute.stderr +++ b/tests/ui/loop-match/invalid-attribute.stderr @@ -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