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 path =
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);
return Some(match (struct_expr, block_tail) {
(Ok(expr), Err(mut err)) => {
@ -1188,8 +1188,7 @@ impl<'a> Parser<'a> {
outer_op.node,
);
let mk_err_expr =
|this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new())));
let mk_err_expr = |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err)));
match inner_op.kind {
ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
@ -1647,7 +1646,6 @@ impl<'a> Parser<'a> {
&mut self,
lo: Span,
await_sp: Span,
attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
let (hi, expr, is_question) = if self.token == token::Not {
// Handle `await!(<expr>)`.
@ -1662,7 +1660,7 @@ impl<'a> Parser<'a> {
ExprKind::Try(_) => ExprKind::Err,
_ => 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)
}
@ -1680,7 +1678,7 @@ impl<'a> Parser<'a> {
// Handle `await { <expr> }`.
// This needs to be handled separately from the next arm to avoid
// 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 {
self.parse_expr()
}
@ -1823,7 +1821,7 @@ impl<'a> Parser<'a> {
err.emit();
// Recover from parse error, callers expect the closing delim to be consumed.
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::{ClosureBinder, StmtKind};
use rustc_ast_pretty::pprust;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics;
@ -45,20 +44,12 @@ macro_rules! maybe_whole_expr {
token::NtPath(path) => {
let path = (**path).clone();
$p.bump();
return Ok($p.mk_expr(
$p.prev_token.span,
ExprKind::Path(None, path),
AttrVec::new(),
));
return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path)));
}
token::NtBlock(block) => {
let block = block.clone();
$p.bump();
return Ok($p.mk_expr(
$p.prev_token.span,
ExprKind::Block(block, None),
AttrVec::new(),
));
return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None)));
}
_ => {}
};
@ -120,7 +111,7 @@ impl<'a> Parser<'a> {
// Special-case handling of `foo(_, _, _)`
err.emit();
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),
},
@ -329,11 +320,9 @@ impl<'a> Parser<'a> {
| AssocOp::GreaterEqual => {
let ast_op = op.to_ast_binop().unwrap();
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
self.mk_expr(span, binary, AttrVec::new())
}
AssocOp::Assign => {
self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span), AttrVec::new())
self.mk_expr(span, binary)
}
AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
AssocOp::AssignOp(k) => {
let aop = match k {
token::Plus => BinOpKind::Add,
@ -348,7 +337,7 @@ impl<'a> Parser<'a> {
token::Shr => BinOpKind::Shr,
};
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 => {
self.span_bug(span, "AssocOp should have been handled by special case")
@ -491,7 +480,7 @@ impl<'a> Parser<'a> {
let limits =
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
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 {
@ -540,7 +529,7 @@ impl<'a> Parser<'a> {
(lo, None)
};
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.collect_tokens_for_expr($attrs, |$this, attrs| {
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,
) -> PResult<'a, P<Expr>> {
let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
this.mk_expr(
this.mk_expr_sp(&lhs, lhs_span, rhs.span),
expr_kind(lhs, rhs),
AttrVec::new(),
)
this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
};
// 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,
),
};
match self.parse_labeled_expr(label, AttrVec::new(), false) {
match self.parse_labeled_expr(label, false) {
Ok(expr) => {
type_err.cancel();
self.struct_span_err(label.ident.span, "malformed loop label")
@ -990,7 +975,7 @@ impl<'a> Parser<'a> {
};
if has_question {
// `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;
}
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 field = ExprKind::Field(base, Ident::new(field, span));
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(...)`.
@ -1182,9 +1167,9 @@ impl<'a> Parser<'a> {
};
let open_paren = self.token.span;
let mut seq = self.parse_paren_expr_seq().map(|args| {
self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new())
});
let mut seq = self
.parse_paren_expr_seq()
.map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
if let Some(expr) =
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()?;
self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?;
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.
@ -1283,11 +1268,7 @@ impl<'a> Parser<'a> {
let args = self.parse_paren_expr_seq()?;
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(
span,
ExprKind::MethodCall(segment, self_arg, args, fn_span),
AttrVec::new(),
))
Ok(self.mk_expr(span, ExprKind::MethodCall(segment, self_arg, args, fn_span)))
} else {
// Field access `expr.f`
if let Some(args) = segment.args {
@ -1299,7 +1280,7 @@ impl<'a> Parser<'a> {
}
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
// 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()`.
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
// could be removed without changing functionality, but it's faster
// 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)) {
self.parse_tuple_parens_expr(attrs)
self.parse_tuple_parens_expr()
} 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) {
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 }`
// then suggest parens around the lhs.
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
@ -1340,65 +1317,66 @@ impl<'a> Parser<'a> {
err
})
} 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() {
self.parse_path_start_expr(attrs)
self.parse_path_start_expr()
} 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) {
self.parse_if_expr(attrs)
self.parse_if_expr()
} else if self.check_keyword(kw::For) {
if self.choose_generics_over_qpath(1) {
self.parse_closure_expr(attrs)
self.parse_closure_expr()
} else {
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) {
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() {
self.parse_labeled_expr(label, attrs, true)
self.parse_labeled_expr(label, true)
} else if self.eat_keyword(kw::Loop) {
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
})
} else if self.eat_keyword(kw::Continue) {
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) {
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
})
} else if self.eat_keyword(kw::Unsafe) {
let sp = self.prev_token.span;
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
.map_err(|mut err| {
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|mut err| {
err.span_label(sp, "while parsing this `unsafe` expression");
err
})
},
)
} else if self.check_inline_const(0) {
self.parse_const_block(lo.to(self.token.span), false)
} else if self.is_do_catch_block() {
self.recover_do_catch(attrs)
self.recover_do_catch()
} else if self.is_try_block() {
self.expect_keyword(kw::Try)?;
self.parse_try_block(lo, attrs)
self.parse_try_block(lo)
} else if self.eat_keyword(kw::Return) {
self.parse_return_expr(attrs)
self.parse_return_expr()
} else if self.eat_keyword(kw::Break) {
self.parse_break_expr(attrs)
self.parse_break_expr()
} else if self.eat_keyword(kw::Yield) {
self.parse_yield_expr(attrs)
self.parse_yield_expr()
} else if self.is_do_yeet() {
self.parse_yeet_expr(attrs)
self.parse_yeet_expr()
} else if self.check_keyword(kw::Let) {
self.parse_let_expr(attrs)
self.parse_let_expr()
} 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) {
// Don't complain about bare semicolons after unclosed braces
// 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.is_async_block() {
// Check for `async {` and `async move {`.
self.parse_async_block(attrs)
self.parse_async_block()
} else {
self.parse_closure_expr(attrs)
self.parse_closure_expr()
}
} 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 {
self.parse_lit_expr(attrs)
self.parse_lit_expr()
}
} 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;
match self.parse_opt_lit() {
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)
}
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;
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
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`.
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)
}
fn parse_array_or_repeat_expr(
&mut self,
attrs: AttrVec,
close_delim: Delimiter,
) -> PResult<'a, P<Expr>> {
fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.bump(); // `[` or other open delim
@ -1499,11 +1473,11 @@ impl<'a> Parser<'a> {
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)
}
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) = self.parse_qpath(PathStyle::Expr)?;
(Some(qself), path)
@ -1525,7 +1499,7 @@ impl<'a> Parser<'a> {
};
(lo.to(self.prev_token.span), ExprKind::MacCall(mac))
} 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() {
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))
};
let expr = self.mk_expr(span, kind, attrs);
let expr = self.mk_expr(span, kind);
self.maybe_recover_from_bad_qpath(expr)
}
@ -1542,22 +1516,21 @@ impl<'a> Parser<'a> {
fn parse_labeled_expr(
&mut self,
label: Label,
attrs: AttrVec,
mut consume_colon: bool,
) -> PResult<'a, P<Expr>> {
let lo = label.ident.span;
let label = Some(label);
let ate_colon = self.eat(&token::Colon);
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) {
self.parse_for_expr(label, lo, attrs)
self.parse_for_expr(label, lo)
} 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))
|| 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
&& (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`.
let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
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();
@ -1651,7 +1624,7 @@ impl<'a> Parser<'a> {
}
/// 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;
self.bump(); // `do`
@ -1668,7 +1641,7 @@ impl<'a> Parser<'a> {
.note("following RFC #2388, the new non-placeholder syntax is `try`")
.emit();
self.parse_try_block(lo, attrs)
self.parse_try_block(lo)
}
/// Parse an expression if the token can begin one.
@ -1677,15 +1650,15 @@ impl<'a> Parser<'a> {
}
/// 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 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)
}
/// 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;
self.bump(); // `do`
@ -1695,7 +1668,7 @@ impl<'a> Parser<'a> {
let span = lo.to(self.prev_token.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)
}
@ -1707,13 +1680,13 @@ impl<'a> Parser<'a> {
/// `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
/// 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 mut label = self.eat_label();
let kind = if label.is_some() && self.token == token::Colon {
// The value expression can be a labeled loop, see issue #86948, e.g.:
// `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(
lexpr.span,
"parentheses are required around this expression to avoid confusion with a labeled break expression",
@ -1755,17 +1728,17 @@ impl<'a> Parser<'a> {
} else {
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)
}
/// 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 kind = ExprKind::Yield(self.parse_expr_opt()?);
let span = lo.to(self.prev_token.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)
}
@ -2009,14 +1982,10 @@ impl<'a> Parser<'a> {
let lo = self.token.span;
let minus_present = self.eat(&token::BinOp(token::Minus));
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 {
Ok(self.mk_expr(
lo.to(self.prev_token.span),
self.mk_unary(UnOp::Neg, expr),
AttrVec::new(),
))
Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr)))
} else {
Ok(expr)
}
@ -2031,13 +2000,9 @@ impl<'a> Parser<'a> {
/// 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
/// expression.
fn maybe_suggest_brackets_instead_of_braces(
&mut self,
lo: Span,
attrs: AttrVec,
) -> Option<P<Expr>> {
fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
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) => {
let hi = snapshot.prev_token.span;
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>,
lo: Span,
blk_mode: BlockCheckMode,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
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);
}
}
@ -2121,19 +2085,18 @@ impl<'a> Parser<'a> {
.emit();
}
let (inner_attrs, blk) = self.parse_block_common(lo, blk_mode)?;
attrs.extend(inner_attrs);
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
}
/// Parse a block which takes no attributes and has no label
fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
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`).
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 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).
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,
lo.to(decl_hi),
),
attrs,
);
// Disable recovery for closure body
@ -2275,19 +2237,13 @@ impl<'a> Parser<'a> {
}
/// 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 cond = self.parse_cond_expr()?;
self.parse_if_after_cond(attrs, lo, cond)
self.parse_if_after_cond(lo, cond)
}
fn parse_if_after_cond(
&mut self,
attrs: AttrVec,
lo: Span,
mut cond: P<Expr>,
) -> PResult<'a, P<Expr>> {
fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> {
let cond_span = cond.span;
// 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.
@ -2343,7 +2299,7 @@ impl<'a> Parser<'a> {
block
};
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(
@ -2385,7 +2341,7 @@ impl<'a> Parser<'a> {
}
/// 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
// being parsed in the right position. It's approximate because it
// 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())
})?;
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).
@ -2419,7 +2375,7 @@ impl<'a> Parser<'a> {
let else_span = self.prev_token.span; // `else`
let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
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)) {
self.parse_simple_block()?
} else {
@ -2442,7 +2398,7 @@ impl<'a> Parser<'a> {
Applicability::MaybeIncorrect,
)
.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) => {
e.cancel();
@ -2479,12 +2435,7 @@ impl<'a> Parser<'a> {
}
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
fn parse_for_expr(
&mut self,
opt_label: Option<Label>,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
// Record whether we are about to parse `for (`.
// This is used below for recovery in case of `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 (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
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) {
@ -2535,35 +2485,31 @@ impl<'a> Parser<'a> {
}
/// Parses a `while` or `while let` expression (`while` token already eaten).
fn parse_while_expr(
&mut self,
opt_label: Option<Label>,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
fn parse_while_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let cond = self.parse_cond_expr().map_err(|mut err| {
err.span_label(lo, "while parsing the condition of this `while` expression");
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(cond.span, "this `while` condition successfully parsed");
err
})?;
attrs.extend(iattrs);
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs))
Ok(self.mk_expr_with_attrs(
lo.to(self.prev_token.span),
ExprKind::While(cond, body, opt_label),
attrs,
))
}
/// Parses `loop { ... }` (`loop` token already eaten).
fn parse_loop_expr(
&mut self,
opt_label: Option<Label>,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
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))
fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
Ok(self.mk_expr_with_attrs(
lo.to(self.prev_token.span),
ExprKind::Loop(body, opt_label),
attrs,
))
}
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).
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 lo = self.prev_token.span;
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@ -2594,7 +2540,7 @@ impl<'a> Parser<'a> {
return Err(e);
}
}
attrs.extend(self.parse_inner_attributes()?);
let attrs = self.parse_inner_attributes()?;
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::CloseDelim(Delimiter::Brace) {
@ -2608,13 +2554,17 @@ impl<'a> Parser<'a> {
if self.token == token::CloseDelim(Delimiter::Brace) {
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;
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.
@ -2874,9 +2824,8 @@ impl<'a> Parser<'a> {
}
/// Parses a `try {...}` expression (`try` token already eaten).
fn parse_try_block(&mut self, span_lo: Span, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
if self.eat_keyword(kw::Catch) {
let mut error = self.struct_span_err(
self.prev_token.span,
@ -2888,7 +2837,7 @@ impl<'a> Parser<'a> {
} else {
let span = span_lo.to(body.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.
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;
self.expect_keyword(kw::Async)?;
let capture_clause = self.parse_capture_clause()?;
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let (attrs, body) = self.parse_inner_attrs_and_block()?;
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 {
@ -2951,14 +2899,13 @@ impl<'a> Parser<'a> {
&mut self,
qself: Option<&ast::QSelf>,
path: &ast::Path,
attrs: &AttrVec,
) -> Option<PResult<'a, P<Expr>>> {
let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
if struct_allowed || self.is_certainly_not_a_block() {
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
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) {
// 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);
@ -3095,7 +3042,6 @@ impl<'a> Parser<'a> {
&mut self,
qself: Option<ast::QSelf>,
pth: ast::Path,
attrs: AttrVec,
recover: bool,
) -> PResult<'a, P<Expr>> {
let lo = pth.span;
@ -3108,7 +3054,7 @@ impl<'a> Parser<'a> {
} else {
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 }`.
@ -3163,7 +3109,7 @@ impl<'a> Parser<'a> {
// Mimic `x: x` for the `x` field shorthand.
let ident = this.parse_ident_common(false)?;
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 {
let ident = this.parse_field_name()?;
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> {
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();
await_expr
}
pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
pub(crate) fn mk_expr_with_attrs<A>(&self, span: Span, kind: ExprKind, attrs: A) -> P<Expr>
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> {
self.mk_expr(span, ExprKind::Err, AttrVec::new())
self.mk_expr(span, ExprKind::Err)
}
/// 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 anon_const = AnonConst {
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;
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).

View File

@ -4,8 +4,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::{
self as ast, AttrVec, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat,
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
self as ast, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
PatKind, Path, QSelf, RangeEnd, RangeSyntax,
};
use rustc_ast_pretty::pprust;
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) {
self.parse_pat_mac_invoc(path)?
} 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)?
} else if self.check(&token::OpenDelim(Delimiter::Brace)) {
self.parse_pat_struct(qself, path)?
@ -807,7 +807,7 @@ impl<'a> Parser<'a> {
(None, self.parse_path(PathStyle::Expr)?)
};
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 {
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> {
// Parse const argument.
let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind {
self.parse_block_expr(
None,
self.token.span,
BlockCheckMode::Default,
ast::AttrVec::new(),
)?
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)?
} else {
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)) {
this.parse_struct_expr(None, path, AttrVec::new(), true)?
this.parse_struct_expr(None, path, true)?
} else {
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| {
@ -179,7 +179,7 @@ impl<'a> Parser<'a> {
StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
} else {
// 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.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;