1
Fork 0

Rollup merge of #127903 - nnethercote:force_collect-improvements, r=petrochenkov

`force_collect` improvements

Yet more cleanups relating to `cfg_attr` processing.

r? ````@petrochenkov````
This commit is contained in:
Matthias Krüger 2024-07-19 10:48:05 +02:00 committed by GitHub
commit 9ada89d9a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 47 additions and 43 deletions

View file

@ -4,6 +4,7 @@ use crate::errors;
use rustc_ast::attr::mk_attr; use rustc_ast::attr::mk_attr;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::{self as ast, AttrItem, AttrStyle}; use rustc_ast::{self as ast, AttrItem, AttrStyle};
use rustc_parse::parser::ForceCollect;
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::FileName; use rustc_span::FileName;
@ -17,13 +18,14 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
)); ));
let start_span = parser.token.span; let start_span = parser.token.span;
let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) { let AttrItem { unsafety, path, args, tokens: _ } =
Ok(ai) => ai, match parser.parse_attr_item(ForceCollect::No) {
Err(err) => { Ok(ai) => ai,
err.emit(); Err(err) => {
continue; err.emit();
} continue;
}; }
};
let end_span = parser.token.span; let end_span = parser.token.span;
if parser.token != token::Eof { if parser.token != token::Eof {
psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) }); psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });

View file

@ -124,7 +124,7 @@ impl<'a> Parser<'a> {
if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer }; if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
this.expect(&token::OpenDelim(Delimiter::Bracket))?; this.expect(&token::OpenDelim(Delimiter::Bracket))?;
let item = this.parse_attr_item(false)?; let item = this.parse_attr_item(ForceCollect::No)?;
this.expect(&token::CloseDelim(Delimiter::Bracket))?; this.expect(&token::CloseDelim(Delimiter::Bracket))?;
let attr_sp = lo.to(this.prev_token.span); let attr_sp = lo.to(this.prev_token.span);
@ -248,16 +248,15 @@ impl<'a> Parser<'a> {
/// PATH /// PATH
/// PATH `=` UNSUFFIXED_LIT /// PATH `=` UNSUFFIXED_LIT
/// The delimiters or `=` are still put into the resulting token stream. /// The delimiters or `=` are still put into the resulting token stream.
pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> { pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> {
maybe_whole!(self, NtMeta, |attr| attr.into_inner()); maybe_whole!(self, NtMeta, |attr| attr.into_inner());
let do_parse = |this: &mut Self| { let do_parse = |this: &mut Self, _empty_attrs| {
let is_unsafe = this.eat_keyword(kw::Unsafe); let is_unsafe = this.eat_keyword(kw::Unsafe);
let unsafety = if is_unsafe { let unsafety = if is_unsafe {
let unsafe_span = this.prev_token.span; let unsafe_span = this.prev_token.span;
this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span); this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
this.expect(&token::OpenDelim(Delimiter::Parenthesis))?; this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
ast::Safety::Unsafe(unsafe_span) ast::Safety::Unsafe(unsafe_span)
} else { } else {
ast::Safety::Default ast::Safety::Default
@ -268,10 +267,10 @@ impl<'a> Parser<'a> {
if is_unsafe { if is_unsafe {
this.expect(&token::CloseDelim(Delimiter::Parenthesis))?; this.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
} }
Ok(ast::AttrItem { unsafety, path, args, tokens: None }) Ok((ast::AttrItem { unsafety, path, args, tokens: None }, false))
}; };
// Attr items don't have attributes // Attr items don't have attributes.
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) } self.collect_tokens_trailing_token(AttrWrapper::empty(), force_collect, do_parse)
} }
/// Parses attributes that appear after the opening of an item. These should /// Parses attributes that appear after the opening of an item. These should
@ -344,7 +343,7 @@ impl<'a> Parser<'a> {
let mut expanded_attrs = Vec::with_capacity(1); let mut expanded_attrs = Vec::with_capacity(1);
while self.token.kind != token::Eof { while self.token.kind != token::Eof {
let lo = self.token.span; let lo = self.token.span;
let item = self.parse_attr_item(true)?; let item = self.parse_attr_item(ForceCollect::Yes)?;
expanded_attrs.push((item, lo.to(self.prev_token.span))); expanded_attrs.push((item, lo.to(self.prev_token.span)));
if !self.eat(&token::Comma) { if !self.eat(&token::Comma) {
break; break;

View file

@ -943,11 +943,10 @@ impl<'a> Parser<'a> {
let initial_semicolon = self.token.span; let initial_semicolon = self.token.span;
while self.eat(&TokenKind::Semi) { while self.eat(&TokenKind::Semi) {
let _ = let _ = self.parse_stmt_without_recovery(false, ForceCollect::No).unwrap_or_else(|e| {
self.parse_stmt_without_recovery(false, ForceCollect::Yes).unwrap_or_else(|e| { e.cancel();
e.cancel(); None
None });
});
} }
expect_err expect_err

View file

@ -171,7 +171,7 @@ impl<'a> Parser<'a> {
NonterminalKind::Path => { NonterminalKind::Path => {
NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?))
} }
NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)), NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)),
NonterminalKind::Vis => { NonterminalKind::Vis => {
NtVis(P(self NtVis(P(self
.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)) .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))

View file

@ -72,6 +72,7 @@ impl<'a> Parser<'a> {
lo, lo,
attrs, attrs,
errors::InvalidVariableDeclarationSub::MissingLet, errors::InvalidVariableDeclarationSub::MissingLet,
force_collect,
)? )?
} else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() { } else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
self.bump(); // `auto` self.bump(); // `auto`
@ -79,6 +80,7 @@ impl<'a> Parser<'a> {
lo, lo,
attrs, attrs,
errors::InvalidVariableDeclarationSub::UseLetNotAuto, errors::InvalidVariableDeclarationSub::UseLetNotAuto,
force_collect,
)? )?
} else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() { } else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
self.bump(); // `var` self.bump(); // `var`
@ -86,6 +88,7 @@ impl<'a> Parser<'a> {
lo, lo,
attrs, attrs,
errors::InvalidVariableDeclarationSub::UseLetNotVar, errors::InvalidVariableDeclarationSub::UseLetNotVar,
force_collect,
)? )?
} else if self.check_path() } else if self.check_path()
&& !self.token.is_qpath_start() && !self.token.is_qpath_start()
@ -96,17 +99,17 @@ impl<'a> Parser<'a> {
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
// that starts like a path (1 token), but it fact not a path. // that starts like a path (1 token), but it fact not a path.
// Also, we avoid stealing syntax from `parse_item_`. // Also, we avoid stealing syntax from `parse_item_`.
match force_collect { let stmt = self.collect_tokens_trailing_token(
ForceCollect::Yes => { AttrWrapper::empty(),
self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))? force_collect,
|this, _empty_attrs| Ok((this.parse_stmt_path_start(lo, attrs)?, false)),
);
match stmt {
Ok(stmt) => stmt,
Err(mut err) => {
self.suggest_add_missing_let_for_stmt(&mut err);
return Err(err);
} }
ForceCollect::No => match self.parse_stmt_path_start(lo, attrs) {
Ok(stmt) => stmt,
Err(mut err) => {
self.suggest_add_missing_let_for_stmt(&mut err);
return Err(err);
}
},
} }
} else if let Some(item) = self.parse_item_common( } else if let Some(item) = self.parse_item_common(
attrs.clone(), attrs.clone(),
@ -123,12 +126,13 @@ impl<'a> Parser<'a> {
self.mk_stmt(lo, StmtKind::Empty) self.mk_stmt(lo, StmtKind::Empty)
} else if self.token != token::CloseDelim(Delimiter::Brace) { } else if self.token != token::CloseDelim(Delimiter::Brace) {
// Remainder are line-expr stmts. // Remainder are line-expr stmts.
let e = match force_collect { let e = self.collect_tokens_trailing_token(
ForceCollect::Yes => self.collect_tokens_no_attrs(|this| { AttrWrapper::empty(),
this.parse_expr_res(Restrictions::STMT_EXPR, attrs) force_collect,
})?, |this, _empty_attrs| {
ForceCollect::No => self.parse_expr_res(Restrictions::STMT_EXPR, attrs)?, Ok((this.parse_expr_res(Restrictions::STMT_EXPR, attrs)?, false))
}; },
)?;
if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) { if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) {
let bl = self.parse_block()?; let bl = self.parse_block()?;
// Destructuring assignment ... else. // Destructuring assignment ... else.
@ -231,13 +235,13 @@ impl<'a> Parser<'a> {
lo: Span, lo: Span,
attrs: AttrWrapper, attrs: AttrWrapper,
subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub, subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub,
force_collect: ForceCollect,
) -> PResult<'a, Stmt> { ) -> PResult<'a, Stmt> {
let stmt = let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| { let local = this.parse_local(attrs)?;
let local = this.parse_local(attrs)?; // FIXME - maybe capture semicolon in recovery?
// FIXME - maybe capture semicolon in recovery? Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), false))
Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), false)) })?;
})?;
self.dcx() self.dcx()
.emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) }); .emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
Ok(stmt) Ok(stmt)