Simplify attribute handling in parse_bottom_expr.

`Parser::parse_bottom_expr` currently constructs an empty `attrs` and
then passes it to a large number of other functions. This makes the code
harder to read than it should be, because it's not clear that many
`attrs` arguments are always empty.

This commit removes `attrs` and the passing, simplifying a lot of
functions. The commit also renames `Parser::mk_expr` (which takes an
`attrs` argument) as `mk_expr_with_attrs`, and introduces a new
`mk_expr` which creates an expression with no attributes, which is the
more common case.
This commit is contained in:
Nicholas Nethercote 2022-08-15 09:58:38 +10:00
parent 1e8497351d
commit 2ef0479568
6 changed files with 159 additions and 208 deletions

View File

@ -734,7 +734,7 @@ impl<'a> Parser<'a> {
let mut snapshot = self.create_snapshot_for_diagnostic(); let mut snapshot = self.create_snapshot_for_diagnostic();
let path = let path =
Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None }; Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
let struct_expr = snapshot.parse_struct_expr(None, path, AttrVec::new(), false); let struct_expr = snapshot.parse_struct_expr(None, path, false);
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No); let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
return Some(match (struct_expr, block_tail) { return Some(match (struct_expr, block_tail) {
(Ok(expr), Err(mut err)) => { (Ok(expr), Err(mut err)) => {
@ -1188,8 +1188,7 @@ impl<'a> Parser<'a> {
outer_op.node, outer_op.node,
); );
let mk_err_expr = let mk_err_expr = |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err)));
|this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new())));
match inner_op.kind { match inner_op.kind {
ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => { ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
@ -1647,7 +1646,6 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
lo: Span, lo: Span,
await_sp: Span, await_sp: Span,
attrs: AttrVec,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let (hi, expr, is_question) = if self.token == token::Not { let (hi, expr, is_question) = if self.token == token::Not {
// Handle `await!(<expr>)`. // Handle `await!(<expr>)`.
@ -1662,7 +1660,7 @@ impl<'a> Parser<'a> {
ExprKind::Try(_) => ExprKind::Err, ExprKind::Try(_) => ExprKind::Err,
_ => ExprKind::Await(expr), _ => ExprKind::Await(expr),
}; };
let expr = self.mk_expr(lo.to(sp), kind, attrs); let expr = self.mk_expr(lo.to(sp), kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
@ -1680,7 +1678,7 @@ impl<'a> Parser<'a> {
// Handle `await { <expr> }`. // Handle `await { <expr> }`.
// This needs to be handled separately from the next arm to avoid // This needs to be handled separately from the next arm to avoid
// interpreting `await { <expr> }?` as `<expr>?.await`. // interpreting `await { <expr> }?` as `<expr>?.await`.
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default, AttrVec::new()) self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)
} else { } else {
self.parse_expr() self.parse_expr()
} }
@ -1823,7 +1821,7 @@ impl<'a> Parser<'a> {
err.emit(); err.emit();
// Recover from parse error, callers expect the closing delim to be consumed. // Recover from parse error, callers expect the closing delim to be consumed.
self.consume_block(delim, ConsumeClosingDelim::Yes); self.consume_block(delim, ConsumeClosingDelim::Yes);
self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err, AttrVec::new()) self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err)
} }
} }
} }

View File

@ -20,7 +20,6 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
use rustc_ast::{ClosureBinder, StmtKind}; use rustc_ast::{ClosureBinder, StmtKind};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::BuiltinLintDiagnostics;
@ -45,20 +44,12 @@ macro_rules! maybe_whole_expr {
token::NtPath(path) => { token::NtPath(path) => {
let path = (**path).clone(); let path = (**path).clone();
$p.bump(); $p.bump();
return Ok($p.mk_expr( return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path)));
$p.prev_token.span,
ExprKind::Path(None, path),
AttrVec::new(),
));
} }
token::NtBlock(block) => { token::NtBlock(block) => {
let block = block.clone(); let block = block.clone();
$p.bump(); $p.bump();
return Ok($p.mk_expr( return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None)));
$p.prev_token.span,
ExprKind::Block(block, None),
AttrVec::new(),
));
} }
_ => {} _ => {}
}; };
@ -120,7 +111,7 @@ impl<'a> Parser<'a> {
// Special-case handling of `foo(_, _, _)` // Special-case handling of `foo(_, _, _)`
err.emit(); err.emit();
self.bump(); self.bump();
Ok(self.mk_expr(self.prev_token.span, ExprKind::Err, AttrVec::new())) Ok(self.mk_expr(self.prev_token.span, ExprKind::Err))
} }
_ => Err(err), _ => Err(err),
}, },
@ -329,11 +320,9 @@ impl<'a> Parser<'a> {
| AssocOp::GreaterEqual => { | AssocOp::GreaterEqual => {
let ast_op = op.to_ast_binop().unwrap(); let ast_op = op.to_ast_binop().unwrap();
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs); let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
self.mk_expr(span, binary, AttrVec::new()) self.mk_expr(span, binary)
}
AssocOp::Assign => {
self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span), AttrVec::new())
} }
AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
AssocOp::AssignOp(k) => { AssocOp::AssignOp(k) => {
let aop = match k { let aop = match k {
token::Plus => BinOpKind::Add, token::Plus => BinOpKind::Add,
@ -348,7 +337,7 @@ impl<'a> Parser<'a> {
token::Shr => BinOpKind::Shr, token::Shr => BinOpKind::Shr,
}; };
let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs); let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
self.mk_expr(span, aopexpr, AttrVec::new()) self.mk_expr(span, aopexpr)
} }
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => { AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
self.span_bug(span, "AssocOp should have been handled by special case") self.span_bug(span, "AssocOp should have been handled by special case")
@ -491,7 +480,7 @@ impl<'a> Parser<'a> {
let limits = let limits =
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
let range = self.mk_range(Some(lhs), rhs, limits); let range = self.mk_range(Some(lhs), rhs, limits);
Ok(self.mk_expr(span, range, AttrVec::new())) Ok(self.mk_expr(span, range))
} }
fn is_at_start_of_range_notation_rhs(&self) -> bool { fn is_at_start_of_range_notation_rhs(&self) -> bool {
@ -540,7 +529,7 @@ impl<'a> Parser<'a> {
(lo, None) (lo, None)
}; };
let range = this.mk_range(None, opt_end, limits); let range = this.mk_range(None, opt_end, limits);
Ok(this.mk_expr(span, range, attrs.into())) Ok(this.mk_expr_with_attrs(span, range, attrs))
}) })
} }
@ -553,7 +542,7 @@ impl<'a> Parser<'a> {
($this:ident, $attrs:expr, |this, _| $body:expr) => { ($this:ident, $attrs:expr, |this, _| $body:expr) => {
$this.collect_tokens_for_expr($attrs, |$this, attrs| { $this.collect_tokens_for_expr($attrs, |$this, attrs| {
let (hi, ex) = $body?; let (hi, ex) = $body?;
Ok($this.mk_expr(lo.to(hi), ex, attrs.into())) Ok($this.mk_expr_with_attrs(lo.to(hi), ex, attrs))
}) })
}; };
} }
@ -705,11 +694,7 @@ impl<'a> Parser<'a> {
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind, expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| { let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
this.mk_expr( this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
this.mk_expr_sp(&lhs, lhs_span, rhs.span),
expr_kind(lhs, rhs),
AttrVec::new(),
)
}; };
// Save the state of the parser before parsing type normally, in case there is a // Save the state of the parser before parsing type normally, in case there is a
@ -737,7 +722,7 @@ impl<'a> Parser<'a> {
segments[0].ident.span, segments[0].ident.span,
), ),
}; };
match self.parse_labeled_expr(label, AttrVec::new(), false) { match self.parse_labeled_expr(label, false) {
Ok(expr) => { Ok(expr) => {
type_err.cancel(); type_err.cancel();
self.struct_span_err(label.ident.span, "malformed loop label") self.struct_span_err(label.ident.span, "malformed loop label")
@ -990,7 +975,7 @@ impl<'a> Parser<'a> {
}; };
if has_question { if has_question {
// `expr?` // `expr?`
e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e), AttrVec::new()); e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
continue; continue;
} }
let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) { let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
@ -1168,7 +1153,7 @@ impl<'a> Parser<'a> {
let span = self.prev_token.span; let span = self.prev_token.span;
let field = ExprKind::Field(base, Ident::new(field, span)); let field = ExprKind::Field(base, Ident::new(field, span));
self.expect_no_suffix(span, "a tuple index", suffix); self.expect_no_suffix(span, "a tuple index", suffix);
self.mk_expr(lo.to(span), field, AttrVec::new()) self.mk_expr(lo.to(span), field)
} }
/// Parse a function call expression, `expr(...)`. /// Parse a function call expression, `expr(...)`.
@ -1182,9 +1167,9 @@ impl<'a> Parser<'a> {
}; };
let open_paren = self.token.span; let open_paren = self.token.span;
let mut seq = self.parse_paren_expr_seq().map(|args| { let mut seq = self
self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new()) .parse_paren_expr_seq()
}); .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
if let Some(expr) = if let Some(expr) =
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot) self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
{ {
@ -1264,7 +1249,7 @@ impl<'a> Parser<'a> {
let index = self.parse_expr()?; let index = self.parse_expr()?;
self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?; self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?;
self.expect(&token::CloseDelim(Delimiter::Bracket))?; self.expect(&token::CloseDelim(Delimiter::Bracket))?;
Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index), AttrVec::new())) Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index)))
} }
/// Assuming we have just parsed `.`, continue parsing into an expression. /// Assuming we have just parsed `.`, continue parsing into an expression.
@ -1283,11 +1268,7 @@ impl<'a> Parser<'a> {
let args = self.parse_paren_expr_seq()?; let args = self.parse_paren_expr_seq()?;
let fn_span = fn_span_lo.to(self.prev_token.span); let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
Ok(self.mk_expr( Ok(self.mk_expr(span, ExprKind::MethodCall(segment, self_arg, args, fn_span)))
span,
ExprKind::MethodCall(segment, self_arg, args, fn_span),
AttrVec::new(),
))
} else { } else {
// Field access `expr.f` // Field access `expr.f`
if let Some(args) = segment.args { if let Some(args) = segment.args {
@ -1299,7 +1280,7 @@ impl<'a> Parser<'a> {
} }
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), AttrVec::new())) Ok(self.mk_expr(span, ExprKind::Field(self_arg, segment.ident)))
} }
} }
@ -1314,10 +1295,6 @@ impl<'a> Parser<'a> {
// Outer attributes are already parsed and will be // Outer attributes are already parsed and will be
// added to the return value after the fact. // added to the return value after the fact.
//
// Therefore, prevent sub-parser from parsing
// attributes by giving them an empty "already-parsed" list.
let attrs = AttrVec::new();
// Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
let lo = self.token.span; let lo = self.token.span;
@ -1325,13 +1302,13 @@ impl<'a> Parser<'a> {
// This match arm is a special-case of the `_` match arm below and // This match arm is a special-case of the `_` match arm below and
// could be removed without changing functionality, but it's faster // could be removed without changing functionality, but it's faster
// to have it here, especially for programs with large constants. // to have it here, especially for programs with large constants.
self.parse_lit_expr(attrs) self.parse_lit_expr()
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
self.parse_tuple_parens_expr(attrs) self.parse_tuple_parens_expr()
} else if self.check(&token::OpenDelim(Delimiter::Brace)) { } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs) self.parse_block_expr(None, lo, BlockCheckMode::Default)
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) { } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
self.parse_closure_expr(attrs).map_err(|mut err| { self.parse_closure_expr().map_err(|mut err| {
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
// then suggest parens around the lhs. // then suggest parens around the lhs.
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) { if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
@ -1340,65 +1317,66 @@ impl<'a> Parser<'a> {
err err
}) })
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) { } else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
self.parse_array_or_repeat_expr(attrs, Delimiter::Bracket) self.parse_array_or_repeat_expr(Delimiter::Bracket)
} else if self.check_path() { } else if self.check_path() {
self.parse_path_start_expr(attrs) self.parse_path_start_expr()
} else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
self.parse_closure_expr(attrs) self.parse_closure_expr()
} else if self.eat_keyword(kw::If) { } else if self.eat_keyword(kw::If) {
self.parse_if_expr(attrs) self.parse_if_expr()
} else if self.check_keyword(kw::For) { } else if self.check_keyword(kw::For) {
if self.choose_generics_over_qpath(1) { if self.choose_generics_over_qpath(1) {
self.parse_closure_expr(attrs) self.parse_closure_expr()
} else { } else {
assert!(self.eat_keyword(kw::For)); assert!(self.eat_keyword(kw::For));
self.parse_for_expr(None, self.prev_token.span, attrs) self.parse_for_expr(None, self.prev_token.span)
} }
} else if self.eat_keyword(kw::While) { } else if self.eat_keyword(kw::While) {
self.parse_while_expr(None, self.prev_token.span, attrs) self.parse_while_expr(None, self.prev_token.span)
} else if let Some(label) = self.eat_label() { } else if let Some(label) = self.eat_label() {
self.parse_labeled_expr(label, attrs, true) self.parse_labeled_expr(label, true)
} else if self.eat_keyword(kw::Loop) { } else if self.eat_keyword(kw::Loop) {
let sp = self.prev_token.span; let sp = self.prev_token.span;
self.parse_loop_expr(None, self.prev_token.span, attrs).map_err(|mut err| { self.parse_loop_expr(None, self.prev_token.span).map_err(|mut err| {
err.span_label(sp, "while parsing this `loop` expression"); err.span_label(sp, "while parsing this `loop` expression");
err err
}) })
} else if self.eat_keyword(kw::Continue) { } else if self.eat_keyword(kw::Continue) {
let kind = ExprKind::Continue(self.eat_label()); let kind = ExprKind::Continue(self.eat_label());
Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
} else if self.eat_keyword(kw::Match) { } else if self.eat_keyword(kw::Match) {
let match_sp = self.prev_token.span; let match_sp = self.prev_token.span;
self.parse_match_expr(attrs).map_err(|mut err| { self.parse_match_expr().map_err(|mut err| {
err.span_label(match_sp, "while parsing this `match` expression"); err.span_label(match_sp, "while parsing this `match` expression");
err err
}) })
} else if self.eat_keyword(kw::Unsafe) { } else if self.eat_keyword(kw::Unsafe) {
let sp = self.prev_token.span; let sp = self.prev_token.span;
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
.map_err(|mut err| { |mut err| {
err.span_label(sp, "while parsing this `unsafe` expression"); err.span_label(sp, "while parsing this `unsafe` expression");
err err
}) },
)
} else if self.check_inline_const(0) { } else if self.check_inline_const(0) {
self.parse_const_block(lo.to(self.token.span), false) self.parse_const_block(lo.to(self.token.span), false)
} else if self.is_do_catch_block() { } else if self.is_do_catch_block() {
self.recover_do_catch(attrs) self.recover_do_catch()
} else if self.is_try_block() { } else if self.is_try_block() {
self.expect_keyword(kw::Try)?; self.expect_keyword(kw::Try)?;
self.parse_try_block(lo, attrs) self.parse_try_block(lo)
} else if self.eat_keyword(kw::Return) { } else if self.eat_keyword(kw::Return) {
self.parse_return_expr(attrs) self.parse_return_expr()
} else if self.eat_keyword(kw::Break) { } else if self.eat_keyword(kw::Break) {
self.parse_break_expr(attrs) self.parse_break_expr()
} else if self.eat_keyword(kw::Yield) { } else if self.eat_keyword(kw::Yield) {
self.parse_yield_expr(attrs) self.parse_yield_expr()
} else if self.is_do_yeet() { } else if self.is_do_yeet() {
self.parse_yeet_expr(attrs) self.parse_yeet_expr()
} else if self.check_keyword(kw::Let) { } else if self.check_keyword(kw::Let) {
self.parse_let_expr(attrs) self.parse_let_expr()
} else if self.eat_keyword(kw::Underscore) { } else if self.eat_keyword(kw::Underscore) {
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
} else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
// Don't complain about bare semicolons after unclosed braces // Don't complain about bare semicolons after unclosed braces
// recovery in order to keep the error count down. Fixing the // recovery in order to keep the error count down. Fixing the
@ -1417,32 +1395,32 @@ impl<'a> Parser<'a> {
if self.check_keyword(kw::Async) { if self.check_keyword(kw::Async) {
if self.is_async_block() { if self.is_async_block() {
// Check for `async {` and `async move {`. // Check for `async {` and `async move {`.
self.parse_async_block(attrs) self.parse_async_block()
} else { } else {
self.parse_closure_expr(attrs) self.parse_closure_expr()
} }
} else if self.eat_keyword(kw::Await) { } else if self.eat_keyword(kw::Await) {
self.recover_incorrect_await_syntax(lo, self.prev_token.span, attrs) self.recover_incorrect_await_syntax(lo, self.prev_token.span)
} else { } else {
self.parse_lit_expr(attrs) self.parse_lit_expr()
} }
} else { } else {
self.parse_lit_expr(attrs) self.parse_lit_expr()
} }
} }
fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_lit_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
match self.parse_opt_lit() { match self.parse_opt_lit() {
Some(literal) => { Some(literal) => {
let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs); let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal));
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
None => self.try_macro_suggestion(), None => self.try_macro_suggestion(),
} }
} }
fn parse_tuple_parens_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_tuple_parens_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
let (es, trailing_comma) = match self.parse_seq_to_end( let (es, trailing_comma) = match self.parse_seq_to_end(
@ -1462,15 +1440,11 @@ impl<'a> Parser<'a> {
// `(e,)` is a tuple with only one field, `e`. // `(e,)` is a tuple with only one field, `e`.
ExprKind::Tup(es) ExprKind::Tup(es)
}; };
let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
fn parse_array_or_repeat_expr( fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
&mut self,
attrs: AttrVec,
close_delim: Delimiter,
) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
self.bump(); // `[` or other open delim self.bump(); // `[` or other open delim
@ -1499,11 +1473,11 @@ impl<'a> Parser<'a> {
ExprKind::Array(vec![first_expr]) ExprKind::Array(vec![first_expr])
} }
}; };
let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
let (qself, path) = if self.eat_lt() { let (qself, path) = if self.eat_lt() {
let (qself, path) = self.parse_qpath(PathStyle::Expr)?; let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
(Some(qself), path) (Some(qself), path)
@ -1525,7 +1499,7 @@ impl<'a> Parser<'a> {
}; };
(lo.to(self.prev_token.span), ExprKind::MacCall(mac)) (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
} else if self.check(&token::OpenDelim(Delimiter::Brace)) && } else if self.check(&token::OpenDelim(Delimiter::Brace)) &&
let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path, &attrs) { let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path) {
if qself.is_some() { if qself.is_some() {
self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
} }
@ -1534,7 +1508,7 @@ impl<'a> Parser<'a> {
(path.span, ExprKind::Path(qself, path)) (path.span, ExprKind::Path(qself, path))
}; };
let expr = self.mk_expr(span, kind, attrs); let expr = self.mk_expr(span, kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
@ -1542,22 +1516,21 @@ impl<'a> Parser<'a> {
fn parse_labeled_expr( fn parse_labeled_expr(
&mut self, &mut self,
label: Label, label: Label,
attrs: AttrVec,
mut consume_colon: bool, mut consume_colon: bool,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let lo = label.ident.span; let lo = label.ident.span;
let label = Some(label); let label = Some(label);
let ate_colon = self.eat(&token::Colon); let ate_colon = self.eat(&token::Colon);
let expr = if self.eat_keyword(kw::While) { let expr = if self.eat_keyword(kw::While) {
self.parse_while_expr(label, lo, attrs) self.parse_while_expr(label, lo)
} else if self.eat_keyword(kw::For) { } else if self.eat_keyword(kw::For) {
self.parse_for_expr(label, lo, attrs) self.parse_for_expr(label, lo)
} else if self.eat_keyword(kw::Loop) { } else if self.eat_keyword(kw::Loop) {
self.parse_loop_expr(label, lo, attrs) self.parse_loop_expr(label, lo)
} else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace)) } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
|| self.token.is_whole_block() || self.token.is_whole_block()
{ {
self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) self.parse_block_expr(label, lo, BlockCheckMode::Default)
} else if !ate_colon } else if !ate_colon
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
{ {
@ -1623,7 +1596,7 @@ impl<'a> Parser<'a> {
// Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`. // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`.
let stmt = self.mk_stmt(span, StmtKind::Expr(expr)); let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span); let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span);
self.mk_expr(span, ExprKind::Block(blk, label), ThinVec::new()) self.mk_expr(span, ExprKind::Block(blk, label))
}); });
err.emit(); err.emit();
@ -1651,7 +1624,7 @@ impl<'a> Parser<'a> {
} }
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
fn recover_do_catch(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
self.bump(); // `do` self.bump(); // `do`
@ -1668,7 +1641,7 @@ impl<'a> Parser<'a> {
.note("following RFC #2388, the new non-placeholder syntax is `try`") .note("following RFC #2388, the new non-placeholder syntax is `try`")
.emit(); .emit();
self.parse_try_block(lo, attrs) self.parse_try_block(lo)
} }
/// Parse an expression if the token can begin one. /// Parse an expression if the token can begin one.
@ -1677,15 +1650,15 @@ impl<'a> Parser<'a> {
} }
/// Parse `"return" expr?`. /// Parse `"return" expr?`.
fn parse_return_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_return_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let kind = ExprKind::Ret(self.parse_expr_opt()?); let kind = ExprKind::Ret(self.parse_expr_opt()?);
let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
/// Parse `"do" "yeet" expr?`. /// Parse `"do" "yeet" expr?`.
fn parse_yeet_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_yeet_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
self.bump(); // `do` self.bump(); // `do`
@ -1695,7 +1668,7 @@ impl<'a> Parser<'a> {
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
self.sess.gated_spans.gate(sym::yeet_expr, span); self.sess.gated_spans.gate(sym::yeet_expr, span);
let expr = self.mk_expr(span, kind, attrs); let expr = self.mk_expr(span, kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
@ -1707,13 +1680,13 @@ impl<'a> Parser<'a> {
/// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
/// expression only gets a warning for compatibility reasons; and a labeled break /// expression only gets a warning for compatibility reasons; and a labeled break
/// with a labeled loop does not even get a warning because there is no ambiguity. /// with a labeled loop does not even get a warning because there is no ambiguity.
fn parse_break_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_break_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let mut label = self.eat_label(); let mut label = self.eat_label();
let kind = if label.is_some() && self.token == token::Colon { let kind = if label.is_some() && self.token == token::Colon {
// The value expression can be a labeled loop, see issue #86948, e.g.: // The value expression can be a labeled loop, see issue #86948, e.g.:
// `loop { break 'label: loop { break 'label 42; }; }` // `loop { break 'label: loop { break 'label 42; }; }`
let lexpr = self.parse_labeled_expr(label.take().unwrap(), AttrVec::new(), true)?; let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?;
self.struct_span_err( self.struct_span_err(
lexpr.span, lexpr.span,
"parentheses are required around this expression to avoid confusion with a labeled break expression", "parentheses are required around this expression to avoid confusion with a labeled break expression",
@ -1755,17 +1728,17 @@ impl<'a> Parser<'a> {
} else { } else {
None None
}; };
let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind), attrs); let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind));
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
/// Parse `"yield" expr?`. /// Parse `"yield" expr?`.
fn parse_yield_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let kind = ExprKind::Yield(self.parse_expr_opt()?); let kind = ExprKind::Yield(self.parse_expr_opt()?);
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
self.sess.gated_spans.gate(sym::generators, span); self.sess.gated_spans.gate(sym::generators, span);
let expr = self.mk_expr(span, kind, attrs); let expr = self.mk_expr(span, kind);
self.maybe_recover_from_bad_qpath(expr) self.maybe_recover_from_bad_qpath(expr)
} }
@ -2009,14 +1982,10 @@ impl<'a> Parser<'a> {
let lo = self.token.span; let lo = self.token.span;
let minus_present = self.eat(&token::BinOp(token::Minus)); let minus_present = self.eat(&token::BinOp(token::Minus));
let lit = self.parse_lit()?; let lit = self.parse_lit()?;
let expr = self.mk_expr(lit.span, ExprKind::Lit(lit), AttrVec::new()); let expr = self.mk_expr(lit.span, ExprKind::Lit(lit));
if minus_present { if minus_present {
Ok(self.mk_expr( Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr)))
lo.to(self.prev_token.span),
self.mk_unary(UnOp::Neg, expr),
AttrVec::new(),
))
} else { } else {
Ok(expr) Ok(expr)
} }
@ -2031,13 +2000,9 @@ impl<'a> Parser<'a> {
/// Emits a suggestion if it looks like the user meant an array but /// Emits a suggestion if it looks like the user meant an array but
/// accidentally used braces, causing the code to be interpreted as a block /// accidentally used braces, causing the code to be interpreted as a block
/// expression. /// expression.
fn maybe_suggest_brackets_instead_of_braces( fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
&mut self,
lo: Span,
attrs: AttrVec,
) -> Option<P<Expr>> {
let mut snapshot = self.create_snapshot_for_diagnostic(); let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_array_or_repeat_expr(attrs, Delimiter::Brace) { match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
Ok(arr) => { Ok(arr) => {
let hi = snapshot.prev_token.span; let hi = snapshot.prev_token.span;
self.struct_span_err(arr.span, "this is a block expression, not an array") self.struct_span_err(arr.span, "this is a block expression, not an array")
@ -2103,10 +2068,9 @@ impl<'a> Parser<'a> {
opt_label: Option<Label>, opt_label: Option<Label>,
lo: Span, lo: Span,
blk_mode: BlockCheckMode, blk_mode: BlockCheckMode,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
if self.is_array_like_block() { if self.is_array_like_block() {
if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo, attrs.clone()) { if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) {
return Ok(arr); return Ok(arr);
} }
} }
@ -2121,19 +2085,18 @@ impl<'a> Parser<'a> {
.emit(); .emit();
} }
let (inner_attrs, blk) = self.parse_block_common(lo, blk_mode)?; let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
attrs.extend(inner_attrs); Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
} }
/// Parse a block which takes no attributes and has no label /// Parse a block which takes no attributes and has no label
fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> { fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
let blk = self.parse_block()?; let blk = self.parse_block()?;
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())) Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None)))
} }
/// Parses a closure expression (e.g., `move |args| expr`). /// Parses a closure expression (e.g., `move |args| expr`).
fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_closure_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
let binder = if self.check_keyword(kw::For) { let binder = if self.check_keyword(kw::For) {
@ -2168,7 +2131,7 @@ impl<'a> Parser<'a> {
_ => { _ => {
// If an explicit return type is given, require a block to appear (RFC 968). // If an explicit return type is given, require a block to appear (RFC 968).
let body_lo = self.token.span; let body_lo = self.token.span;
self.parse_block_expr(None, body_lo, BlockCheckMode::Default, AttrVec::new())? self.parse_block_expr(None, body_lo, BlockCheckMode::Default)?
} }
}; };
@ -2199,7 +2162,6 @@ impl<'a> Parser<'a> {
body, body,
lo.to(decl_hi), lo.to(decl_hi),
), ),
attrs,
); );
// Disable recovery for closure body // Disable recovery for closure body
@ -2275,19 +2237,13 @@ impl<'a> Parser<'a> {
} }
/// Parses an `if` expression (`if` token already eaten). /// Parses an `if` expression (`if` token already eaten).
fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_if_expr(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let cond = self.parse_cond_expr()?; let cond = self.parse_cond_expr()?;
self.parse_if_after_cond(lo, cond)
self.parse_if_after_cond(attrs, lo, cond)
} }
fn parse_if_after_cond( fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> {
&mut self,
attrs: AttrVec,
lo: Span,
mut cond: P<Expr>,
) -> PResult<'a, P<Expr>> {
let cond_span = cond.span; let cond_span = cond.span;
// Tries to interpret `cond` as either a missing expression if it's a block, // Tries to interpret `cond` as either a missing expression if it's a block,
// or as an unfinished expression if it's a binop and the RHS is a block. // or as an unfinished expression if it's a binop and the RHS is a block.
@ -2343,7 +2299,7 @@ impl<'a> Parser<'a> {
block block
}; };
let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None }; let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs)) Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
} }
fn error_missing_if_then_block( fn error_missing_if_then_block(
@ -2385,7 +2341,7 @@ impl<'a> Parser<'a> {
} }
/// Parses a `let $pat = $expr` pseudo-expression. /// Parses a `let $pat = $expr` pseudo-expression.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
// This is a *approximate* heuristic that detects if `let` chains are // This is a *approximate* heuristic that detects if `let` chains are
// being parsed in the right position. It's approximate because it // being parsed in the right position. It's approximate because it
// doesn't deny all invalid `let` expressions, just completely wrong usages. // doesn't deny all invalid `let` expressions, just completely wrong usages.
@ -2411,7 +2367,7 @@ impl<'a> Parser<'a> {
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
})?; })?;
let span = lo.to(expr.span); let span = lo.to(expr.span);
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span), attrs)) Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span)))
} }
/// Parses an `else { ... }` expression (`else` token already eaten). /// Parses an `else { ... }` expression (`else` token already eaten).
@ -2419,7 +2375,7 @@ impl<'a> Parser<'a> {
let else_span = self.prev_token.span; // `else` let else_span = self.prev_token.span; // `else`
let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery. let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
let expr = if self.eat_keyword(kw::If) { let expr = if self.eat_keyword(kw::If) {
self.parse_if_expr(AttrVec::new())? self.parse_if_expr()?
} else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) { } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
self.parse_simple_block()? self.parse_simple_block()?
} else { } else {
@ -2442,7 +2398,7 @@ impl<'a> Parser<'a> {
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
) )
.emit(); .emit();
self.parse_if_after_cond(AttrVec::new(), cond.span.shrink_to_lo(), cond)? self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
} }
Err(e) => { Err(e) => {
e.cancel(); e.cancel();
@ -2479,12 +2435,7 @@ impl<'a> Parser<'a> {
} }
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
fn parse_for_expr( fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
&mut self,
opt_label: Option<Label>,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
// Record whether we are about to parse `for (`. // Record whether we are about to parse `for (`.
// This is used below for recovery in case of `for ( $stuff ) $block` // This is used below for recovery in case of `for ( $stuff ) $block`
// in which case we will suggest `for $stuff $block`. // in which case we will suggest `for $stuff $block`.
@ -2507,11 +2458,10 @@ impl<'a> Parser<'a> {
let pat = self.recover_parens_around_for_head(pat, begin_paren); let pat = self.recover_parens_around_for_head(pat, begin_paren);
let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
} }
fn error_missing_in_for_loop(&mut self) { fn error_missing_in_for_loop(&mut self) {
@ -2535,35 +2485,31 @@ impl<'a> Parser<'a> {
} }
/// Parses a `while` or `while let` expression (`while` token already eaten). /// Parses a `while` or `while let` expression (`while` token already eaten).
fn parse_while_expr( fn parse_while_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
&mut self,
opt_label: Option<Label>,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
let cond = self.parse_cond_expr().map_err(|mut err| { let cond = self.parse_cond_expr().map_err(|mut err| {
err.span_label(lo, "while parsing the condition of this `while` expression"); err.span_label(lo, "while parsing the condition of this `while` expression");
err err
})?; })?;
let (iattrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| { let (attrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| {
err.span_label(lo, "while parsing the body of this `while` expression"); err.span_label(lo, "while parsing the body of this `while` expression");
err.span_label(cond.span, "this `while` condition successfully parsed"); err.span_label(cond.span, "this `while` condition successfully parsed");
err err
})?; })?;
attrs.extend(iattrs); Ok(self.mk_expr_with_attrs(
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs)) lo.to(self.prev_token.span),
ExprKind::While(cond, body, opt_label),
attrs,
))
} }
/// Parses `loop { ... }` (`loop` token already eaten). /// Parses `loop { ... }` (`loop` token already eaten).
fn parse_loop_expr( fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
&mut self, let (attrs, body) = self.parse_inner_attrs_and_block()?;
opt_label: Option<Label>, Ok(self.mk_expr_with_attrs(
lo: Span, lo.to(self.prev_token.span),
mut attrs: AttrVec, ExprKind::Loop(body, opt_label),
) -> PResult<'a, P<Expr>> { attrs,
let (iattrs, body) = self.parse_inner_attrs_and_block()?; ))
attrs.extend(iattrs);
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::Loop(body, opt_label), attrs))
} }
pub(crate) fn eat_label(&mut self) -> Option<Label> { pub(crate) fn eat_label(&mut self) -> Option<Label> {
@ -2574,7 +2520,7 @@ impl<'a> Parser<'a> {
} }
/// Parses a `match ... { ... }` expression (`match` token already eaten). /// Parses a `match ... { ... }` expression (`match` token already eaten).
fn parse_match_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_match_expr(&mut self) -> PResult<'a, P<Expr>> {
let match_span = self.prev_token.span; let match_span = self.prev_token.span;
let lo = self.prev_token.span; let lo = self.prev_token.span;
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@ -2594,7 +2540,7 @@ impl<'a> Parser<'a> {
return Err(e); return Err(e);
} }
} }
attrs.extend(self.parse_inner_attributes()?); let attrs = self.parse_inner_attributes()?;
let mut arms: Vec<Arm> = Vec::new(); let mut arms: Vec<Arm> = Vec::new();
while self.token != token::CloseDelim(Delimiter::Brace) { while self.token != token::CloseDelim(Delimiter::Brace) {
@ -2608,13 +2554,17 @@ impl<'a> Parser<'a> {
if self.token == token::CloseDelim(Delimiter::Brace) { if self.token == token::CloseDelim(Delimiter::Brace) {
self.bump(); self.bump();
} }
return Ok(self.mk_expr(span, ExprKind::Match(scrutinee, arms), attrs)); return Ok(self.mk_expr_with_attrs(
span,
ExprKind::Match(scrutinee, arms),
attrs,
));
} }
} }
} }
let hi = self.token.span; let hi = self.token.span;
self.bump(); self.bump();
Ok(self.mk_expr(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)) Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs))
} }
/// Attempt to recover from match arm body with statements and no surrounding braces. /// Attempt to recover from match arm body with statements and no surrounding braces.
@ -2874,9 +2824,8 @@ impl<'a> Parser<'a> {
} }
/// Parses a `try {...}` expression (`try` token already eaten). /// Parses a `try {...}` expression (`try` token already eaten).
fn parse_try_block(&mut self, span_lo: Span, mut attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
let (iattrs, body) = self.parse_inner_attrs_and_block()?; let (attrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
if self.eat_keyword(kw::Catch) { if self.eat_keyword(kw::Catch) {
let mut error = self.struct_span_err( let mut error = self.struct_span_err(
self.prev_token.span, self.prev_token.span,
@ -2888,7 +2837,7 @@ impl<'a> Parser<'a> {
} else { } else {
let span = span_lo.to(body.span); let span = span_lo.to(body.span);
self.sess.gated_spans.gate(sym::try_blocks, span); self.sess.gated_spans.gate(sym::try_blocks, span);
Ok(self.mk_expr(span, ExprKind::TryBlock(body), attrs)) Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs))
} }
} }
@ -2910,14 +2859,13 @@ impl<'a> Parser<'a> {
} }
/// Parses an `async move? {...}` expression. /// Parses an `async move? {...}` expression.
fn parse_async_block(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_async_block(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span; let lo = self.token.span;
self.expect_keyword(kw::Async)?; self.expect_keyword(kw::Async)?;
let capture_clause = self.parse_capture_clause()?; let capture_clause = self.parse_capture_clause()?;
let (iattrs, body) = self.parse_inner_attrs_and_block()?; let (attrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let kind = ExprKind::Async(capture_clause, DUMMY_NODE_ID, body); let kind = ExprKind::Async(capture_clause, DUMMY_NODE_ID, body);
Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
} }
fn is_async_block(&self) -> bool { fn is_async_block(&self) -> bool {
@ -2951,14 +2899,13 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
qself: Option<&ast::QSelf>, qself: Option<&ast::QSelf>,
path: &ast::Path, path: &ast::Path,
attrs: &AttrVec,
) -> Option<PResult<'a, P<Expr>>> { ) -> Option<PResult<'a, P<Expr>>> {
let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
if struct_allowed || self.is_certainly_not_a_block() { if struct_allowed || self.is_certainly_not_a_block() {
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) { if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
return Some(Err(err)); return Some(Err(err));
} }
let expr = self.parse_struct_expr(qself.cloned(), path.clone(), attrs.clone(), true); let expr = self.parse_struct_expr(qself.cloned(), path.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) { if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here. // This is a struct literal, but we don't can't accept them here.
self.error_struct_lit_not_allowed_here(path.span, expr.span); self.error_struct_lit_not_allowed_here(path.span, expr.span);
@ -3095,7 +3042,6 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
qself: Option<ast::QSelf>, qself: Option<ast::QSelf>,
pth: ast::Path, pth: ast::Path,
attrs: AttrVec,
recover: bool, recover: bool,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let lo = pth.span; let lo = pth.span;
@ -3108,7 +3054,7 @@ impl<'a> Parser<'a> {
} else { } else {
ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base })) ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base }))
}; };
Ok(self.mk_expr(span, expr, attrs)) Ok(self.mk_expr(span, expr))
} }
/// Use in case of error after field-looking code: `S { foo: () with a }`. /// Use in case of error after field-looking code: `S { foo: () with a }`.
@ -3163,7 +3109,7 @@ impl<'a> Parser<'a> {
// Mimic `x: x` for the `x` field shorthand. // Mimic `x: x` for the `x` field shorthand.
let ident = this.parse_ident_common(false)?; let ident = this.parse_ident_common(false)?;
let path = ast::Path::from_ident(ident); let path = ast::Path::from_ident(ident);
(ident, this.mk_expr(ident.span, ExprKind::Path(None, path), AttrVec::new())) (ident, this.mk_expr(ident.span, ExprKind::Path(None, path)))
} else { } else {
let ident = this.parse_field_name()?; let ident = this.parse_field_name()?;
this.error_on_eq_field_init(ident); this.error_on_eq_field_init(ident);
@ -3268,17 +3214,25 @@ impl<'a> Parser<'a> {
fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> { fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new()); let await_expr = self.mk_expr(span, ExprKind::Await(self_arg));
self.recover_from_await_method_call(); self.recover_from_await_method_call();
await_expr await_expr
} }
pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> { pub(crate) fn mk_expr_with_attrs<A>(&self, span: Span, kind: ExprKind, attrs: A) -> P<Expr>
P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None }) where
A: Into<AttrVec>,
{
P(Expr { kind, span, attrs: attrs.into(), id: DUMMY_NODE_ID, tokens: None })
}
// njn: rename
pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> {
P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None })
} }
pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> { pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
self.mk_expr(span, ExprKind::Err, AttrVec::new()) self.mk_expr(span, ExprKind::Err)
} }
/// Create expression span ensuring the span of the parent node /// Create expression span ensuring the span of the parent node

View File

@ -1116,10 +1116,14 @@ impl<'a> Parser<'a> {
let (attrs, blk) = self.parse_inner_attrs_and_block()?; let (attrs, blk) = self.parse_inner_attrs_and_block()?;
let anon_const = AnonConst { let anon_const = AnonConst {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
value: self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()), value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
}; };
let blk_span = anon_const.value.span; let blk_span = anon_const.value.span;
Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::from(attrs))) Ok(self.mk_expr_with_attrs(
span.to(blk_span),
ExprKind::ConstBlock(anon_const),
AttrVec::from(attrs),
))
} }
/// Parses mutability (`mut` or nothing). /// Parses mutability (`mut` or nothing).

View File

@ -4,8 +4,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter}; use rustc_ast::token::{self, Delimiter};
use rustc_ast::{ use rustc_ast::{
self as ast, AttrVec, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, self as ast, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
}; };
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
@ -385,7 +385,7 @@ impl<'a> Parser<'a> {
if qself.is_none() && self.check(&token::Not) { if qself.is_none() && self.check(&token::Not) {
self.parse_pat_mac_invoc(path)? self.parse_pat_mac_invoc(path)?
} else if let Some(form) = self.parse_range_end() { } else if let Some(form) = self.parse_range_end() {
let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new()); let begin = self.mk_expr(span, ExprKind::Path(qself, path));
self.parse_pat_range_begin_with(begin, form)? self.parse_pat_range_begin_with(begin, form)?
} else if self.check(&token::OpenDelim(Delimiter::Brace)) { } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
self.parse_pat_struct(qself, path)? self.parse_pat_struct(qself, path)?
@ -807,7 +807,7 @@ impl<'a> Parser<'a> {
(None, self.parse_path(PathStyle::Expr)?) (None, self.parse_path(PathStyle::Expr)?)
}; };
let hi = self.prev_token.span; let hi = self.prev_token.span;
Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), AttrVec::new())) Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path)))
} else { } else {
self.parse_literal_maybe_minus() self.parse_literal_maybe_minus()
} }

View File

@ -652,12 +652,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> { pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
// Parse const argument. // Parse const argument.
let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind { let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind {
self.parse_block_expr( self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)?
None,
self.token.span,
BlockCheckMode::Default,
ast::AttrVec::new(),
)?
} else { } else {
self.handle_unambiguous_unbraced_const_arg()? self.handle_unambiguous_unbraced_const_arg()?
}; };

View File

@ -130,10 +130,10 @@ impl<'a> Parser<'a> {
} }
let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) { let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) {
this.parse_struct_expr(None, path, AttrVec::new(), true)? this.parse_struct_expr(None, path, true)?
} else { } else {
let hi = this.prev_token.span; let hi = this.prev_token.span;
this.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new()) this.mk_expr(lo.to(hi), ExprKind::Path(None, path))
}; };
let expr = this.with_res(Restrictions::STMT_EXPR, |this| { let expr = this.with_res(Restrictions::STMT_EXPR, |this| {
@ -179,7 +179,7 @@ impl<'a> Parser<'a> {
StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
} else { } else {
// Since none of the above applied, this is an expression statement macro. // Since none of the above applied, this is an expression statement macro.
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new()); let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?; let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;