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.
This commit is contained in:
Aaron Hill 2021-01-22 13:28:08 -05:00
parent 7e0241c637
commit 0b411f56e1
No known key found for this signature in database
GPG key ID: B4087E510E98B164
9 changed files with 621 additions and 407 deletions

View file

@ -1,4 +1,4 @@
use super::{Parser, PathStyle};
use super::{ForceCollect, Parser, PathStyle, TrailingToken};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P;
@ -938,16 +938,24 @@ impl<'a> Parser<'a> {
}
}
fields.push(match self.parse_pat_field(lo, attrs) {
Ok(field) => field,
Err(err) => {
if let Some(mut delayed_err) = delayed_err {
delayed_err.emit();
}
return Err(err);
}
});
ate_comma = self.eat(&token::Comma);
let field =
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
let field = match this.parse_pat_field(lo, attrs) {
Ok(field) => Ok(field),
Err(err) => {
if let Some(mut delayed_err) = delayed_err.take() {
delayed_err.emit();
}
return Err(err);
}
}?;
ate_comma = this.eat(&token::Comma);
// We just ate a comma, so there's no need to use
// `TrailingToken::Comma`
Ok((field, TrailingToken::None))
})?;
fields.push(field)
}
if let Some(mut err) = delayed_err {