Skip to content

Commit 7d65809

Browse files
committed
Avoid double-handling of attributes in collect_tokens.
By keeping track of attributes that have been previously processed. This has no external effect for now, but is necessary for #124141, which removes nonterminals.
1 parent d7455a2 commit 7d65809

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

compiler/rustc_parse/src/parser/attr_wrapper.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,20 @@ impl<'a> Parser<'a> {
256256
res?
257257
};
258258

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+
259273
// When we're not in "definite capture mode", then skip collecting and
260274
// return early if either of the following conditions hold.
261275
// - `None`: Our target doesn't support tokens at all (e.g. `NtIdent`).
@@ -269,7 +283,7 @@ impl<'a> Parser<'a> {
269283
// tokens.
270284
let definite_capture_mode = self.capture_cfg
271285
&& matches!(self.capture_state.capturing, Capturing::Yes)
272-
&& has_cfg_or_cfg_attr(ret.attrs());
286+
&& has_cfg_or_cfg_attr(&ret_attrs);
273287
if !definite_capture_mode && matches!(ret.tokens_mut(), None | Some(Some(_))) {
274288
return Ok(ret);
275289
}
@@ -289,7 +303,7 @@ impl<'a> Parser<'a> {
289303
// outer and inner attributes. So this check is more precise than
290304
// the earlier `needs_tokens` check, and we don't need to
291305
// check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
292-
|| needs_tokens(ret.attrs())
306+
|| needs_tokens(&ret_attrs)
293307
// - We are in "definite capture mode", which requires that there
294308
// are `#[cfg]` or `#[cfg_attr]` attributes. (During normal
295309
// non-`capture_cfg` parsing, we don't need any special capturing
@@ -328,7 +342,7 @@ impl<'a> Parser<'a> {
328342
// `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
329343
// which means the relevant tokens will be removed. (More details below.)
330344
let mut inner_attr_parser_replacements = Vec::new();
331-
for attr in ret.attrs() {
345+
for attr in ret_attrs.iter() {
332346
if attr.style == ast::AttrStyle::Inner {
333347
if let Some(inner_attr_parser_range) =
334348
self.capture_state.inner_attr_parser_ranges.remove(&attr.id)
@@ -418,7 +432,7 @@ impl<'a> Parser<'a> {
418432
// cfg-expand this AST node.
419433
let start_pos =
420434
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 };
422436
tokens_used = true;
423437
self.capture_state
424438
.parser_replacements
@@ -428,6 +442,7 @@ impl<'a> Parser<'a> {
428442
// the outermost call to this method.
429443
self.capture_state.parser_replacements.clear();
430444
self.capture_state.inner_attr_parser_ranges.clear();
445+
self.capture_state.seen_attrs.clear();
431446
}
432447
assert!(tokens_used); // check we didn't create `tokens` unnecessarily
433448
Ok(ret)

compiler/rustc_parse/src/parser/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_ast::{
3232
VisibilityKind, DUMMY_NODE_ID,
3333
};
3434
use rustc_ast_pretty::pprust;
35-
use rustc_data_structures::fx::FxHashMap;
35+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3636
use rustc_data_structures::sync::Lrc;
3737
use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
3838
use rustc_session::parse::ParseSess;
@@ -183,7 +183,7 @@ pub struct Parser<'a> {
183183
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
184184
// it doesn't unintentionally get bigger.
185185
#[cfg(target_pointer_width = "64")]
186-
rustc_data_structures::static_assert_size!(Parser<'_>, 256);
186+
rustc_data_structures::static_assert_size!(Parser<'_>, 288);
187187

188188
/// Stores span information about a closure.
189189
#[derive(Clone, Debug)]
@@ -260,6 +260,7 @@ struct CaptureState {
260260
capturing: Capturing,
261261
parser_replacements: Vec<ParserReplacement>,
262262
inner_attr_parser_ranges: FxHashMap<AttrId, ParserRange>,
263+
seen_attrs: FxHashSet<AttrId>,
263264
}
264265

265266
/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
@@ -457,6 +458,7 @@ impl<'a> Parser<'a> {
457458
capturing: Capturing::No,
458459
parser_replacements: Vec::new(),
459460
inner_attr_parser_ranges: Default::default(),
461+
seen_attrs: Default::default(),
460462
},
461463
current_closure: None,
462464
recovery: Recovery::Allowed,

0 commit comments

Comments
 (0)