@@ -256,6 +256,20 @@ impl<'a> Parser<'a> {
256
256
res?
257
257
} ;
258
258
259
+ // Ignore any attributes we've previously processed. This happens when
260
+ // an inner call to `collect_tokens` returns an AST node and then an
261
+ // outer call ends up with the same AST node without any additional
262
+ // wrapping layer.
263
+ let ret_attrs: AttrVec = ret
264
+ . attrs ( )
265
+ . iter ( )
266
+ . cloned ( )
267
+ . filter ( |attr| {
268
+ let is_unseen = self . capture_state . seen_attrs . insert ( attr. id ) ;
269
+ is_unseen
270
+ } )
271
+ . collect ( ) ;
272
+
259
273
// When we're not in "definite capture mode", then skip collecting and
260
274
// return early if either of the following conditions hold.
261
275
// - `None`: Our target doesn't support tokens at all (e.g. `NtIdent`).
@@ -269,7 +283,7 @@ impl<'a> Parser<'a> {
269
283
// tokens.
270
284
let definite_capture_mode = self . capture_cfg
271
285
&& matches ! ( self . capture_state. capturing, Capturing :: Yes )
272
- && has_cfg_or_cfg_attr ( ret . attrs ( ) ) ;
286
+ && has_cfg_or_cfg_attr ( & ret_attrs ) ;
273
287
if !definite_capture_mode && matches ! ( ret. tokens_mut( ) , None | Some ( Some ( _) ) ) {
274
288
return Ok ( ret) ;
275
289
}
@@ -289,7 +303,7 @@ impl<'a> Parser<'a> {
289
303
// outer and inner attributes. So this check is more precise than
290
304
// the earlier `needs_tokens` check, and we don't need to
291
305
// check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
292
- || needs_tokens ( ret . attrs ( ) )
306
+ || needs_tokens ( & ret_attrs )
293
307
// - We are in "definite capture mode", which requires that there
294
308
// are `#[cfg]` or `#[cfg_attr]` attributes. (During normal
295
309
// non-`capture_cfg` parsing, we don't need any special capturing
@@ -328,7 +342,7 @@ impl<'a> Parser<'a> {
328
342
// `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
329
343
// which means the relevant tokens will be removed. (More details below.)
330
344
let mut inner_attr_parser_replacements = Vec :: new ( ) ;
331
- for attr in ret . attrs ( ) {
345
+ for attr in ret_attrs . iter ( ) {
332
346
if attr. style == ast:: AttrStyle :: Inner {
333
347
if let Some ( inner_attr_parser_range) =
334
348
self . capture_state . inner_attr_parser_ranges . remove ( & attr. id )
@@ -418,7 +432,7 @@ impl<'a> Parser<'a> {
418
432
// cfg-expand this AST node.
419
433
let start_pos =
420
434
if has_outer_attrs { attrs. start_pos . unwrap ( ) } else { collect_pos. start_pos } ;
421
- let target = AttrsTarget { attrs : ret . attrs ( ) . iter ( ) . cloned ( ) . collect ( ) , tokens } ;
435
+ let target = AttrsTarget { attrs : ret_attrs , tokens } ;
422
436
tokens_used = true ;
423
437
self . capture_state
424
438
. parser_replacements
@@ -428,6 +442,7 @@ impl<'a> Parser<'a> {
428
442
// the outermost call to this method.
429
443
self . capture_state . parser_replacements . clear ( ) ;
430
444
self . capture_state . inner_attr_parser_ranges . clear ( ) ;
445
+ self . capture_state . seen_attrs . clear ( ) ;
431
446
}
432
447
assert ! ( tokens_used) ; // check we didn't create `tokens` unnecessarily
433
448
Ok ( ret)
0 commit comments