@@ -26,24 +26,29 @@ macro_rules! attribute_groups {
2626 (
2727 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
2828 ) => {
29- pub(crate) static $name: LazyLock<(
30- BTreeMap<&'static [Symbol], Vec<Box<dyn Fn(&AcceptContext<'_>, &ArgParser<'_>) + Send + Sync>>>,
31- Vec<Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>>
32- )> = LazyLock::new(|| {
33- let mut accepts = BTreeMap::<_, Vec<Box<dyn Fn(&AcceptContext<'_>, &ArgParser<'_>) + Send + Sync>>>::new();
34- let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>>::new();
29+ type Accepts = BTreeMap<
30+ &'static [Symbol],
31+ Box<dyn Send + Sync + Fn(&AcceptContext<'_>, &ArgParser<'_>)>
32+ >;
33+ type Finalizes = Vec<
34+ Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>
35+ >;
36+ pub(crate) static $name: LazyLock<(Accepts, Finalizes)> = LazyLock::new(|| {
37+ let mut accepts = Accepts::new();
38+ let mut finalizes = Finalizes::new();
3539 $(
3640 {
3741 thread_local! {
3842 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
3943 };
4044
4145 for (k, v) in <$names>::ATTRIBUTES {
42- accepts.entry (*k).or_default().push( Box::new(|cx, args| {
46+ let old = accepts.insert (*k, Box::new(|cx, args| {
4347 STATE_OBJECT.with_borrow_mut(|s| {
4448 v(s, cx, args)
4549 })
4650 }));
51+ assert!(old.is_none());
4752 }
4853
4954 finalizes.push(Box::new(|cx| {
@@ -110,7 +115,8 @@ impl<'a> Deref for AcceptContext<'a> {
110115
111116/// Context given to every attribute parser during finalization.
112117///
113- /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create errors, for example.
118+ /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
119+ /// errors, for example.
114120pub(crate) struct FinalizeContext<'a> {
115121 /// The parse context, gives access to the session and the
116122 /// diagnostics context.
@@ -141,10 +147,9 @@ pub struct AttributeParser<'sess> {
141147 sess: &'sess Session,
142148 features: Option<&'sess Features>,
143149
144- /// *only * parse attributes with this symbol.
150+ /// *Only * parse attributes with this symbol.
145151 ///
146- /// Used in cases where we want the lowering infrastructure for
147- /// parse just a single attribute.
152+ /// Used in cases where we want the lowering infrastructure for parse just a single attribute.
148153 parse_only: Option<Symbol>,
149154
150155 /// Can be used to instruct parsers to reduce the number of diagnostics it emits.
@@ -157,9 +162,9 @@ impl<'sess> AttributeParser<'sess> {
157162 /// One example where this is necessary, is to parse `feature` attributes themselves for
158163 /// example.
159164 ///
160- /// Try to use this as little as possible. Attributes *should* be lowered during `rustc_ast_lowering`.
161- /// Some attributes require access to features to parse, which would crash if you tried to do so
162- /// through [`parse_limited`](Self::parse_limited).
165+ /// Try to use this as little as possible. Attributes *should* be lowered during
166+ /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
167+ /// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
163168 ///
164169 /// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
165170 /// that symbol are picked out of the list of instructions and parsed. Those are returned.
@@ -217,19 +222,18 @@ impl<'sess> AttributeParser<'sess> {
217222 let group_cx = FinalizeContext { cx: self, target_span };
218223
219224 for attr in attrs {
220- // if we're only looking for a single attribute,
221- // skip all the ones we don't care about
225+ // If we're only looking for a single attribute, skip all the ones we don't care about.
222226 if let Some(expected) = self.parse_only {
223227 if !attr.has_name(expected) {
224228 continue;
225229 }
226230 }
227231
228- // sometimes , for example for `#![doc = include_str!("readme.md")]`,
232+ // Sometimes , for example for `#![doc = include_str!("readme.md")]`,
229233 // doc still contains a non-literal. You might say, when we're lowering attributes
230234 // that's expanded right? But no, sometimes, when parsing attributes on macros,
231235 // we already use the lowering logic and these are still there. So, when `omit_doc`
232- // is set we *also* want to ignore these
236+ // is set we *also* want to ignore these.
233237 if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
234238 continue;
235239 }
@@ -263,21 +267,17 @@ impl<'sess> AttributeParser<'sess> {
263267 let (path, args) = parser.deconstruct();
264268 let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
265269
266- if let Some(accepts) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
267- for f in accepts {
268- let cx = AcceptContext {
269- group_cx: &group_cx,
270- attr_span: lower_span(attr.span),
271- };
270+ if let Some(accept) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
271+ let cx =
272+ AcceptContext { group_cx: &group_cx, attr_span: lower_span(attr.span) };
272273
273- f(&cx, &args)
274- }
274+ accept(&cx, &args)
275275 } else {
276- // if we're here, we must be compiling a tool attribute... Or someone forgot to
277- // parse their fancy new attribute. Let's warn them in any case. If you are that
278- // person, and you really your attribute should remain unparsed, carefully read the
279- // documentation in this module and if you still think so you can add an exception
280- // to this assertion.
276+ // If we're here, we must be compiling a tool attribute... Or someone
277+ // forgot to parse their fancy new attribute. Let's warn them in any case.
278+ // If you are that person, and you really think your attribute should
279+ // remain unparsed, carefully read the documentation in this module and if
280+ // you still think so you can add an exception to this assertion.
281281
282282 // FIXME(jdonszelmann): convert other attributes, and check with this that
283283 // we caught em all
0 commit comments