Skip to content

Commit 4a57048

Browse files
Rollup merge of rust-lang#152288 - JonathanBrouwer:one_accepter_per_attr, r=jdonszelmann
Allow only a single accepter per attribute This is what we discussed last thursday, that we don't need to support this. r? @jdonszelmann
2 parents 011954d + fd7ff90 commit 4a57048

2 files changed

Lines changed: 42 additions & 38 deletions

File tree

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cell::RefCell;
22
use std::collections::BTreeMap;
3+
use std::collections::btree_map::Entry;
34
use std::ops::{Deref, DerefMut};
45
use std::sync::LazyLock;
56

@@ -61,7 +62,7 @@ use crate::target_checking::AllowedTargets;
6162
type GroupType<S> = LazyLock<GroupTypeInner<S>>;
6263

6364
pub(super) struct GroupTypeInner<S: Stage> {
64-
pub(super) accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
65+
pub(super) accepters: BTreeMap<&'static [Symbol], GroupTypeInnerAccept<S>>,
6566
}
6667

6768
pub(super) struct GroupTypeInnerAccept<S: Stage> {
@@ -101,27 +102,32 @@ macro_rules! attribute_parsers {
101102
@[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
102103
) => {
103104
pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
104-
let mut accepters = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
105+
let mut accepters = BTreeMap::<_, GroupTypeInnerAccept<$stage>>::new();
105106
$(
106107
{
107108
thread_local! {
108109
static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
109110
};
110111

111112
for (path, template, accept_fn) in <$names>::ATTRIBUTES {
112-
accepters.entry(*path).or_default().push(GroupTypeInnerAccept {
113-
template: *template,
114-
accept_fn: Box::new(|cx, args| {
115-
STATE_OBJECT.with_borrow_mut(|s| {
116-
accept_fn(s, cx, args)
117-
})
118-
}),
119-
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
120-
finalizer: Box::new(|cx| {
121-
let state = STATE_OBJECT.take();
122-
state.finalize(cx)
123-
}),
124-
});
113+
match accepters.entry(*path) {
114+
Entry::Vacant(e) => {
115+
e.insert(GroupTypeInnerAccept {
116+
template: *template,
117+
accept_fn: Box::new(|cx, args| {
118+
STATE_OBJECT.with_borrow_mut(|s| {
119+
accept_fn(s, cx, args)
120+
})
121+
}),
122+
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
123+
finalizer: Box::new(|cx| {
124+
let state = STATE_OBJECT.take();
125+
state.finalize(cx)
126+
})
127+
});
128+
}
129+
Entry::Occupied(_) => panic!("Attribute {path:?} has multiple accepters"),
130+
}
125131
}
126132
}
127133
)*

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
327327
let parts =
328328
n.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
329329

330-
if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
330+
if let Some(accept) = S::parsers().accepters.get(parts.as_slice()) {
331331
let Some(args) = ArgParser::from_attr_args(
332332
args,
333333
&parts,
@@ -368,28 +368,26 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
368368
continue;
369369
}
370370

371-
for accept in accepts {
372-
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
373-
shared: SharedContext {
374-
cx: self,
375-
target_span,
376-
target,
377-
emit_lint: &mut emit_lint,
378-
},
379-
attr_span,
380-
inner_span: lower_span(n.item.span()),
381-
attr_style: attr.style,
382-
parsed_description: ParsedDescription::Attribute,
383-
template: &accept.template,
384-
attr_path: attr_path.clone(),
385-
};
386-
387-
(accept.accept_fn)(&mut cx, &args);
388-
finalizers.push(&accept.finalizer);
389-
390-
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
391-
Self::check_target(&accept.allowed_targets, target, &mut cx);
392-
}
371+
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
372+
shared: SharedContext {
373+
cx: self,
374+
target_span,
375+
target,
376+
emit_lint: &mut emit_lint,
377+
},
378+
attr_span,
379+
inner_span: lower_span(n.item.span()),
380+
attr_style: attr.style,
381+
parsed_description: ParsedDescription::Attribute,
382+
template: &accept.template,
383+
attr_path: attr_path.clone(),
384+
};
385+
386+
(accept.accept_fn)(&mut cx, &args);
387+
finalizers.push(&accept.finalizer);
388+
389+
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
390+
Self::check_target(&accept.allowed_targets, target, &mut cx);
393391
}
394392
} else {
395393
// If we're here, we must be compiling a tool attribute... Or someone

0 commit comments

Comments
 (0)