mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 14:43:24 +00:00
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:
parent
1e8497351d
commit
2ef0479568
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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()?
|
||||
};
|
||||
|
@ -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))?;
|
||||
|
Loading…
Reference in New Issue
Block a user