Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -142,34 +142,32 @@ 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! {
static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
};

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| {
accept_fn(s, cx, args)
})
}),
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 }
});
};
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a cap of one when single is set I guess haha, or even a smallvec, idk if it makes a diff

Copy link
Copy Markdown
Contributor Author

@JonathanBrouwer JonathanBrouwer Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think attr.len() is low for almost all realistic scenarios, so checking if single would probably be more expensive than just allocating a few extra spaces sometimes.

I am planning to see if I can win some more performance in a followup PR, will experiment with this then :)


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 {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion tests/pretty/delegation-inherit-attributes.pp
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}

Expand Down
20 changes: 10 additions & 10 deletions tests/pretty/delegation-inline-attribute.pp
Original file line number Diff line number Diff line change
Expand Up @@ -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) }

Expand All @@ -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() }

Expand All @@ -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() }
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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

16 changes: 8 additions & 8 deletions tests/ui/loop-match/invalid-attribute.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
Expand All @@ -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