Skip to content

Commit 0b411f5

Browse files
committed
Require passing an AttrWrapper to collect_tokens_trailing_token
This is a pure refactoring split out from #80689. It represents the most invasive part of that PR, requiring changes in every caller of `parse_outer_attributes` In order to eagerly expand `#[cfg]` attributes while preserving the original `TokenStream`, we need to know the range of tokens that corresponds to every attribute target. This is accomplished by making `parse_outer_attributes` return an opaque `AttrWrapper` struct. An `AttrWrapper` must be converted to a plain `AttrVec` by passing it to `collect_tokens_trailing_token`. This makes it difficult to accidentally construct an AST node with attributes without calling `collect_tokens_trailing_token`, since AST nodes store an `AttrVec`, not an `AttrWrapper`. As a result, we now call `collect_tokens_trailing_token` for attribute targets which only support inert attributes, such as generic arguments and struct fields. Currently, the constructed `LazyTokenStream` is simply discarded. Future PRs will record the token range corresponding to the attribute target, allowing those tokens to be removed from an enclosing `collect_tokens_trailing_token` call if necessary.
1 parent 7e0241c commit 0b411f5

File tree

9 files changed

+623
-409
lines changed

9 files changed

+623
-409
lines changed

Diff for: compiler/rustc_ast/src/ast.rs

+15
Original file line numberDiff line numberDiff line change
@@ -2975,3 +2975,18 @@ macro_rules! derive_has_tokens {
29752975
derive_has_tokens! {
29762976
Item, Expr, Ty, AttrItem, Visibility, Path, Block, Pat
29772977
}
2978+
2979+
macro_rules! derive_has_attrs_no_tokens {
2980+
($($ty:path),*) => { $(
2981+
impl HasTokens for $ty {
2982+
fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {}
2983+
}
2984+
)* }
2985+
}
2986+
2987+
// These ast nodes only support inert attributes, so they don't
2988+
// store tokens (since nothing can observe them)
2989+
derive_has_attrs_no_tokens! {
2990+
StructField, Arm,
2991+
Field, FieldPat, Variant, Param, GenericParam
2992+
}

Diff for: compiler/rustc_parse/src/parser/attr.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Parser, PathStyle};
1+
use super::{AttrWrapper, Parser, PathStyle};
22
use rustc_ast as ast;
33
use rustc_ast::attr;
44
use rustc_ast::token::{self, Nonterminal};
@@ -26,7 +26,7 @@ pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPo
2626

2727
impl<'a> Parser<'a> {
2828
/// Parses attributes that appear before an item.
29-
pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
29+
pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
3030
let mut attrs: Vec<ast::Attribute> = Vec::new();
3131
let mut just_parsed_doc_comment = false;
3232
loop {
@@ -74,7 +74,7 @@ impl<'a> Parser<'a> {
7474
break;
7575
}
7676
}
77-
Ok(attrs)
77+
Ok(AttrWrapper { attrs })
7878
}
7979

8080
/// Matches `attribute = # ! [ meta_item ]`.
@@ -89,7 +89,8 @@ impl<'a> Parser<'a> {
8989
inner_parse_policy, self.token
9090
);
9191
let lo = self.token.span;
92-
self.collect_tokens(|this| {
92+
// Attributse can't have attributes of their own
93+
self.collect_tokens_no_attrs(|this| {
9394
if this.eat(&token::Pound) {
9495
let style = if this.eat(&token::Not) {
9596
ast::AttrStyle::Inner
@@ -163,7 +164,8 @@ impl<'a> Parser<'a> {
163164
let args = this.parse_attr_args()?;
164165
Ok(ast::AttrItem { path, args, tokens: None })
165166
};
166-
if capture_tokens { self.collect_tokens(do_parse) } else { do_parse(self) }?
167+
// Attr items don't have attributes
168+
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }?
167169
})
168170
}
169171

0 commit comments

Comments
 (0)