|
|
|
@ -103,7 +103,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
self.collect_tokens_no_attrs(|this| this.parse_expr())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
|
|
|
|
|
pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> {
|
|
|
|
|
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a sequence of expressions delimited by parentheses.
|
|
|
|
|
fn parse_paren_expr_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
|
|
|
|
|
fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
|
|
|
|
|
self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -136,7 +136,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
r: Restrictions,
|
|
|
|
|
already_parsed_attrs: Option<AttrWrapper>,
|
|
|
|
|
) -> PResult<'a, P<Expr>> {
|
|
|
|
|
self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
|
|
|
|
|
self.with_res(r, |this| this.parse_expr_assoc(already_parsed_attrs))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses an associative expression.
|
|
|
|
@ -144,15 +144,15 @@ impl<'a> Parser<'a> {
|
|
|
|
|
/// This parses an expression accounting for associativity and precedence of the operators in
|
|
|
|
|
/// the expression.
|
|
|
|
|
#[inline]
|
|
|
|
|
fn parse_assoc_expr(
|
|
|
|
|
fn parse_expr_assoc(
|
|
|
|
|
&mut self,
|
|
|
|
|
already_parsed_attrs: Option<AttrWrapper>,
|
|
|
|
|
) -> PResult<'a, P<Expr>> {
|
|
|
|
|
self.parse_assoc_expr_with(0, already_parsed_attrs.into())
|
|
|
|
|
self.parse_expr_assoc_with(0, already_parsed_attrs.into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses an associative expression with operators of at least `min_prec` precedence.
|
|
|
|
|
pub(super) fn parse_assoc_expr_with(
|
|
|
|
|
pub(super) fn parse_expr_assoc_with(
|
|
|
|
|
&mut self,
|
|
|
|
|
min_prec: usize,
|
|
|
|
|
lhs: LhsExpr,
|
|
|
|
@ -167,9 +167,9 @@ impl<'a> Parser<'a> {
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
if self.token.is_range_separator() {
|
|
|
|
|
return self.parse_prefix_range_expr(attrs);
|
|
|
|
|
return self.parse_expr_prefix_range(attrs);
|
|
|
|
|
} else {
|
|
|
|
|
self.parse_prefix_expr(attrs)?
|
|
|
|
|
self.parse_expr_prefix(attrs)?
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let last_type_ascription_set = self.last_type_ascription.is_some();
|
|
|
|
@ -293,7 +293,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
|
|
|
|
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
|
|
|
|
|
// generalise it to the Fixity::None code.
|
|
|
|
|
lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?;
|
|
|
|
|
lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -306,7 +306,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
Fixity::None => 1,
|
|
|
|
|
};
|
|
|
|
|
let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
|
|
|
|
|
this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
|
|
|
|
this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
|
|
|
@ -458,7 +458,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
|
|
|
|
|
/// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
|
|
|
|
|
/// The other two variants are handled in `parse_prefix_range_expr` below.
|
|
|
|
|
fn parse_range_expr(
|
|
|
|
|
fn parse_expr_range(
|
|
|
|
|
&mut self,
|
|
|
|
|
prec: usize,
|
|
|
|
|
lhs: P<Expr>,
|
|
|
|
@ -466,7 +466,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
cur_op_span: Span,
|
|
|
|
|
) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
|
|
|
|
Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
|
|
|
|
|
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
@ -491,7 +491,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
|
|
|
|
|
fn parse_prefix_range_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
// Check for deprecated `...` syntax.
|
|
|
|
|
if self.token == token::DotDotDot {
|
|
|
|
|
self.err_dotdotdot_syntax(self.token.span);
|
|
|
|
@ -518,7 +518,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
this.bump();
|
|
|
|
|
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
|
|
|
|
|
// RHS must be parsed with more associativity than the dots.
|
|
|
|
|
this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
|
|
|
|
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
|
|
|
|
.map(|x| (lo.to(x.span), Some(x)))?
|
|
|
|
|
} else {
|
|
|
|
|
(lo, None)
|
|
|
|
@ -529,7 +529,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a prefix-unary-operator expr.
|
|
|
|
|
fn parse_prefix_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_prefix(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
|
|
|
|
let lo = self.token.span;
|
|
|
|
|
|
|
|
|
@ -547,20 +547,20 @@ impl<'a> Parser<'a> {
|
|
|
|
|
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
|
|
|
|
|
match this.token.uninterpolate().kind {
|
|
|
|
|
// `!expr`
|
|
|
|
|
token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
|
|
|
|
|
token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
|
|
|
|
|
// `~expr`
|
|
|
|
|
token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
|
|
|
|
|
// `-expr`
|
|
|
|
|
token::BinOp(token::Minus) => {
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
|
|
|
|
|
}
|
|
|
|
|
// `*expr`
|
|
|
|
|
token::BinOp(token::Star) => {
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
|
|
|
|
|
}
|
|
|
|
|
// `&expr` and `&&expr`
|
|
|
|
|
token::BinOp(token::And) | token::AndAnd => {
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
|
|
|
|
|
}
|
|
|
|
|
// `+lit`
|
|
|
|
|
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
|
|
|
|
@ -579,7 +579,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
this.sess.emit_err(err);
|
|
|
|
|
|
|
|
|
|
this.bump();
|
|
|
|
|
this.parse_prefix_expr(None)
|
|
|
|
|
this.parse_expr_prefix(None)
|
|
|
|
|
}
|
|
|
|
|
// Recover from `++x`:
|
|
|
|
|
token::BinOp(token::Plus)
|
|
|
|
@ -592,28 +592,28 @@ impl<'a> Parser<'a> {
|
|
|
|
|
this.bump();
|
|
|
|
|
this.bump();
|
|
|
|
|
|
|
|
|
|
let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
|
|
|
|
|
let operand_expr = this.parse_expr_dot_or_call(Default::default())?;
|
|
|
|
|
this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
|
|
|
|
|
}
|
|
|
|
|
token::Ident(..) if this.token.is_keyword(kw::Box) => {
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
|
|
|
|
|
make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
|
|
|
|
|
}
|
|
|
|
|
token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
|
|
|
|
|
make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
|
|
|
|
|
}
|
|
|
|
|
_ => return this.parse_dot_or_call_expr(Some(attrs)),
|
|
|
|
|
_ => return this.parse_expr_dot_or_call(Some(attrs)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
|
|
|
|
|
fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
|
|
|
|
|
self.bump();
|
|
|
|
|
let expr = self.parse_prefix_expr(None);
|
|
|
|
|
let expr = self.parse_expr_prefix(None);
|
|
|
|
|
let (span, expr) = self.interpolated_or_expr_span(expr)?;
|
|
|
|
|
Ok((lo.to(span), expr))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
let (span, expr) = self.parse_prefix_expr_common(lo)?;
|
|
|
|
|
fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
let (span, expr) = self.parse_expr_prefix_common(lo)?;
|
|
|
|
|
Ok((span, self.mk_unary(op, expr)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -621,12 +621,12 @@ impl<'a> Parser<'a> {
|
|
|
|
|
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
self.sess.emit_err(errors::TildeAsUnaryOperator(lo));
|
|
|
|
|
|
|
|
|
|
self.parse_unary_expr(lo, UnOp::Not)
|
|
|
|
|
self.parse_expr_unary(lo, UnOp::Not)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `box expr`.
|
|
|
|
|
fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
let (span, expr) = self.parse_prefix_expr_common(lo)?;
|
|
|
|
|
fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
let (span, expr) = self.parse_expr_prefix_common(lo)?;
|
|
|
|
|
self.sess.gated_spans.gate(sym::box_syntax, span);
|
|
|
|
|
Ok((span, ExprKind::Box(expr)))
|
|
|
|
|
}
|
|
|
|
@ -664,7 +664,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
self.parse_unary_expr(lo, UnOp::Not)
|
|
|
|
|
self.parse_expr_unary(lo, UnOp::Not)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
|
|
|
|
@ -722,7 +722,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
segments[0].ident.span,
|
|
|
|
|
),
|
|
|
|
|
};
|
|
|
|
|
match self.parse_labeled_expr(label, false) {
|
|
|
|
|
match self.parse_expr_labeled(label, false) {
|
|
|
|
|
Ok(expr) => {
|
|
|
|
|
type_err.cancel();
|
|
|
|
|
self.sess.emit_err(errors::MalformedLoopLabel {
|
|
|
|
@ -816,7 +816,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
("cast", None)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
|
|
|
|
|
let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?;
|
|
|
|
|
|
|
|
|
|
// Check if an illegal postfix operator has been added after the cast.
|
|
|
|
|
// If the resulting expression is not a cast, it is an illegal postfix operator.
|
|
|
|
@ -887,15 +887,15 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
|
|
|
|
|
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
|
|
|
|
self.expect_and()?;
|
|
|
|
|
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
|
|
|
|
|
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
|
|
|
|
|
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
|
|
|
|
|
let expr = if self.token.is_range_separator() {
|
|
|
|
|
self.parse_prefix_range_expr(None)
|
|
|
|
|
self.parse_expr_prefix_range(None)
|
|
|
|
|
} else {
|
|
|
|
|
self.parse_prefix_expr(None)
|
|
|
|
|
self.parse_expr_prefix(None)
|
|
|
|
|
};
|
|
|
|
|
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
|
|
|
|
|
let span = lo.to(hi);
|
|
|
|
@ -925,16 +925,16 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
|
|
|
|
|
fn parse_dot_or_call_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
|
|
|
|
self.collect_tokens_for_expr(attrs, |this, attrs| {
|
|
|
|
|
let base = this.parse_bottom_expr();
|
|
|
|
|
let base = this.parse_expr_bottom();
|
|
|
|
|
let (span, base) = this.interpolated_or_expr_span(base)?;
|
|
|
|
|
this.parse_dot_or_call_expr_with(base, span, attrs)
|
|
|
|
|
this.parse_expr_dot_or_call_with(base, span, attrs)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(super) fn parse_dot_or_call_expr_with(
|
|
|
|
|
pub(super) fn parse_expr_dot_or_call_with(
|
|
|
|
|
&mut self,
|
|
|
|
|
e0: P<Expr>,
|
|
|
|
|
lo: Span,
|
|
|
|
@ -943,7 +943,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
// Stitch the list of outer attributes onto the return value.
|
|
|
|
|
// A little bit ugly, but the best way given the current code
|
|
|
|
|
// structure
|
|
|
|
|
let res = self.parse_dot_or_call_expr_with_(e0, lo);
|
|
|
|
|
let res = self.parse_expr_dot_or_call_with_(e0, lo);
|
|
|
|
|
if attrs.is_empty() {
|
|
|
|
|
res
|
|
|
|
|
} else {
|
|
|
|
@ -957,7 +957,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
loop {
|
|
|
|
|
let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
|
|
|
|
|
// we are using noexpect here because we don't expect a `?` directly after a `return`
|
|
|
|
@ -980,15 +980,15 @@ impl<'a> Parser<'a> {
|
|
|
|
|
};
|
|
|
|
|
if has_dot {
|
|
|
|
|
// expr.f
|
|
|
|
|
e = self.parse_dot_suffix_expr(lo, e)?;
|
|
|
|
|
e = self.parse_expr_dot_suffix(lo, e)?;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if self.expr_is_complete(&e) {
|
|
|
|
|
return Ok(e);
|
|
|
|
|
}
|
|
|
|
|
e = match self.token.kind {
|
|
|
|
|
token::OpenDelim(Delimiter::Parenthesis) => self.parse_fn_call_expr(lo, e),
|
|
|
|
|
token::OpenDelim(Delimiter::Bracket) => self.parse_index_expr(lo, e)?,
|
|
|
|
|
token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
|
|
|
|
|
token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
|
|
|
|
|
_ => return Ok(e),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1000,14 +1000,14 @@ impl<'a> Parser<'a> {
|
|
|
|
|
&& self.look_ahead(3, |t| t.can_begin_expr())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_dot_suffix(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
match self.token.uninterpolate().kind {
|
|
|
|
|
token::Ident(..) => self.parse_dot_suffix(base, lo),
|
|
|
|
|
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
|
|
|
|
|
Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None))
|
|
|
|
|
Ok(self.parse_expr_tuple_field_access(lo, base, symbol, suffix, None))
|
|
|
|
|
}
|
|
|
|
|
token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
|
|
|
|
|
Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix))
|
|
|
|
|
Ok(self.parse_expr_tuple_field_access_float(lo, base, symbol, suffix))
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
self.error_unexpected_after_dot();
|
|
|
|
@ -1029,7 +1029,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
|
|
|
|
|
// we should break everything including floats into more basic proc-macro style
|
|
|
|
|
// tokens in the lexer (probably preferable).
|
|
|
|
|
fn parse_tuple_field_access_expr_float(
|
|
|
|
|
fn parse_expr_tuple_field_access_float(
|
|
|
|
|
&mut self,
|
|
|
|
|
lo: Span,
|
|
|
|
|
base: P<Expr>,
|
|
|
|
@ -1072,7 +1072,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
match &*components {
|
|
|
|
|
// 1e2
|
|
|
|
|
[IdentLike(i)] => {
|
|
|
|
|
self.parse_tuple_field_access_expr(lo, base, Symbol::intern(&i), suffix, None)
|
|
|
|
|
self.parse_expr_tuple_field_access(lo, base, Symbol::intern(&i), suffix, None)
|
|
|
|
|
}
|
|
|
|
|
// 1.
|
|
|
|
|
[IdentLike(i), Punct('.')] => {
|
|
|
|
@ -1088,7 +1088,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
let symbol = Symbol::intern(&i);
|
|
|
|
|
self.token = Token::new(token::Ident(symbol, false), ident_span);
|
|
|
|
|
let next_token = (Token::new(token::Dot, dot_span), self.token_spacing);
|
|
|
|
|
self.parse_tuple_field_access_expr(lo, base, symbol, None, Some(next_token))
|
|
|
|
|
self.parse_expr_tuple_field_access(lo, base, symbol, None, Some(next_token))
|
|
|
|
|
}
|
|
|
|
|
// 1.2 | 1.2e3
|
|
|
|
|
[IdentLike(i1), Punct('.'), IdentLike(i2)] => {
|
|
|
|
@ -1109,11 +1109,11 @@ impl<'a> Parser<'a> {
|
|
|
|
|
// See issue #76399 and PR #76285 for more details
|
|
|
|
|
let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone);
|
|
|
|
|
let base1 =
|
|
|
|
|
self.parse_tuple_field_access_expr(lo, base, symbol1, None, Some(next_token1));
|
|
|
|
|
self.parse_expr_tuple_field_access(lo, base, symbol1, None, Some(next_token1));
|
|
|
|
|
let symbol2 = Symbol::intern(&i2);
|
|
|
|
|
let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span);
|
|
|
|
|
self.bump_with((next_token2, self.token_spacing)); // `.`
|
|
|
|
|
self.parse_tuple_field_access_expr(lo, base1, symbol2, suffix, None)
|
|
|
|
|
self.parse_expr_tuple_field_access(lo, base1, symbol2, suffix, None)
|
|
|
|
|
}
|
|
|
|
|
// 1e+ | 1e- (recovered)
|
|
|
|
|
[IdentLike(_), Punct('+' | '-')] |
|
|
|
|
@ -1131,7 +1131,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_tuple_field_access_expr(
|
|
|
|
|
fn parse_expr_tuple_field_access(
|
|
|
|
|
&mut self,
|
|
|
|
|
lo: Span,
|
|
|
|
|
base: P<Expr>,
|
|
|
|
@ -1152,7 +1152,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse a function call expression, `expr(...)`.
|
|
|
|
|
fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
|
|
|
|
|
fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
|
|
|
|
|
let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
|
|
|
|
|
&& self.look_ahead_type_ascription_as_field()
|
|
|
|
|
{
|
|
|
|
@ -1163,7 +1163,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
let open_paren = self.token.span;
|
|
|
|
|
|
|
|
|
|
let mut seq = self
|
|
|
|
|
.parse_paren_expr_seq()
|
|
|
|
|
.parse_expr_paren_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)
|
|
|
|
@ -1236,7 +1236,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse an indexing expression `expr[...]`.
|
|
|
|
|
fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let prev_span = self.prev_token.span;
|
|
|
|
|
let open_delim_span = self.token.span;
|
|
|
|
|
self.bump(); // `[`
|
|
|
|
@ -1259,7 +1259,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
|
|
|
|
|
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
|
|
|
|
// Method call `expr.f()`
|
|
|
|
|
let args = self.parse_paren_expr_seq()?;
|
|
|
|
|
let args = self.parse_expr_paren_seq()?;
|
|
|
|
|
let fn_span = fn_span_lo.to(self.prev_token.span);
|
|
|
|
|
let span = lo.to(self.prev_token.span);
|
|
|
|
|
Ok(self.mk_expr(
|
|
|
|
@ -1287,7 +1287,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
///
|
|
|
|
|
/// N.B., this does not parse outer attributes, and is private because it only works
|
|
|
|
|
/// correctly if called from `parse_dot_or_call_expr()`.
|
|
|
|
|
fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
maybe_recover_from_interpolated_ty_qpath!(self, true);
|
|
|
|
|
maybe_whole_expr!(self);
|
|
|
|
|
|
|
|
|
@ -1300,13 +1300,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()
|
|
|
|
|
self.parse_expr_lit()
|
|
|
|
|
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
|
|
|
|
self.parse_tuple_parens_expr()
|
|
|
|
|
self.parse_expr_tuple_parens()
|
|
|
|
|
} else if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
|
|
|
|
self.parse_block_expr(None, lo, BlockCheckMode::Default)
|
|
|
|
|
self.parse_expr_block(None, lo, BlockCheckMode::Default)
|
|
|
|
|
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
|
|
|
|
|
self.parse_closure_expr().map_err(|mut err| {
|
|
|
|
|
self.parse_expr_closure().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) {
|
|
|
|
@ -1315,42 +1315,42 @@ impl<'a> Parser<'a> {
|
|
|
|
|
err
|
|
|
|
|
})
|
|
|
|
|
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
|
|
|
|
|
self.parse_array_or_repeat_expr(Delimiter::Bracket)
|
|
|
|
|
self.parse_expr_array_or_repeat(Delimiter::Bracket)
|
|
|
|
|
} else if self.check_path() {
|
|
|
|
|
self.parse_path_start_expr()
|
|
|
|
|
self.parse_expr_path_start()
|
|
|
|
|
} else if self.check_keyword(kw::Move)
|
|
|
|
|
|| self.check_keyword(kw::Static)
|
|
|
|
|
|| self.check_const_closure()
|
|
|
|
|
{
|
|
|
|
|
self.parse_closure_expr()
|
|
|
|
|
self.parse_expr_closure()
|
|
|
|
|
} else if self.eat_keyword(kw::If) {
|
|
|
|
|
self.parse_if_expr()
|
|
|
|
|
self.parse_expr_if()
|
|
|
|
|
} else if self.check_keyword(kw::For) {
|
|
|
|
|
if self.choose_generics_over_qpath(1) {
|
|
|
|
|
self.parse_closure_expr()
|
|
|
|
|
self.parse_expr_closure()
|
|
|
|
|
} else {
|
|
|
|
|
assert!(self.eat_keyword(kw::For));
|
|
|
|
|
self.parse_for_expr(None, self.prev_token.span)
|
|
|
|
|
self.parse_expr_for(None, self.prev_token.span)
|
|
|
|
|
}
|
|
|
|
|
} else if self.eat_keyword(kw::While) {
|
|
|
|
|
self.parse_while_expr(None, self.prev_token.span)
|
|
|
|
|
self.parse_expr_while(None, self.prev_token.span)
|
|
|
|
|
} else if let Some(label) = self.eat_label() {
|
|
|
|
|
self.parse_labeled_expr(label, true)
|
|
|
|
|
self.parse_expr_labeled(label, true)
|
|
|
|
|
} else if self.eat_keyword(kw::Loop) {
|
|
|
|
|
let sp = self.prev_token.span;
|
|
|
|
|
self.parse_loop_expr(None, self.prev_token.span).map_err(|mut err| {
|
|
|
|
|
self.parse_expr_loop(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::Match) {
|
|
|
|
|
let match_sp = self.prev_token.span;
|
|
|
|
|
self.parse_match_expr().map_err(|mut err| {
|
|
|
|
|
self.parse_expr_match().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)).map_err(
|
|
|
|
|
self.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|
|
|
|
|
|mut err| {
|
|
|
|
|
err.span_label(sp, "while parsing this `unsafe` expression");
|
|
|
|
|
err
|
|
|
|
@ -1364,17 +1364,17 @@ impl<'a> Parser<'a> {
|
|
|
|
|
self.expect_keyword(kw::Try)?;
|
|
|
|
|
self.parse_try_block(lo)
|
|
|
|
|
} else if self.eat_keyword(kw::Return) {
|
|
|
|
|
self.parse_return_expr()
|
|
|
|
|
self.parse_expr_return()
|
|
|
|
|
} else if self.eat_keyword(kw::Continue) {
|
|
|
|
|
self.parse_continue_expr(lo)
|
|
|
|
|
self.parse_expr_continue(lo)
|
|
|
|
|
} else if self.eat_keyword(kw::Break) {
|
|
|
|
|
self.parse_break_expr()
|
|
|
|
|
self.parse_expr_break()
|
|
|
|
|
} else if self.eat_keyword(kw::Yield) {
|
|
|
|
|
self.parse_yield_expr()
|
|
|
|
|
self.parse_expr_yield()
|
|
|
|
|
} else if self.is_do_yeet() {
|
|
|
|
|
self.parse_yeet_expr()
|
|
|
|
|
self.parse_expr_yeet()
|
|
|
|
|
} else if self.check_keyword(kw::Let) {
|
|
|
|
|
self.parse_let_expr()
|
|
|
|
|
self.parse_expr_let()
|
|
|
|
|
} else if self.eat_keyword(kw::Underscore) {
|
|
|
|
|
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
|
|
|
|
|
} else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
|
|
|
|
@ -1397,19 +1397,19 @@ impl<'a> Parser<'a> {
|
|
|
|
|
// Check for `async {` and `async move {`.
|
|
|
|
|
self.parse_async_block()
|
|
|
|
|
} else {
|
|
|
|
|
self.parse_closure_expr()
|
|
|
|
|
self.parse_expr_closure()
|
|
|
|
|
}
|
|
|
|
|
} else if self.eat_keyword(kw::Await) {
|
|
|
|
|
self.recover_incorrect_await_syntax(lo, self.prev_token.span)
|
|
|
|
|
} else {
|
|
|
|
|
self.parse_lit_expr()
|
|
|
|
|
self.parse_expr_lit()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
self.parse_lit_expr()
|
|
|
|
|
self.parse_expr_lit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_lit_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let lo = self.token.span;
|
|
|
|
|
match self.parse_opt_token_lit() {
|
|
|
|
|
Some((token_lit, _)) => {
|
|
|
|
@ -1420,7 +1420,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_tuple_parens_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_tuple_parens(&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(
|
|
|
|
@ -1444,7 +1444,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
self.maybe_recover_from_bad_qpath(expr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let lo = self.token.span;
|
|
|
|
|
self.bump(); // `[` or other open delim
|
|
|
|
|
|
|
|
|
@ -1457,7 +1457,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
let first_expr = self.parse_expr()?;
|
|
|
|
|
if self.eat(&token::Semi) {
|
|
|
|
|
// Repeating array syntax: `[ 0; 512 ]`
|
|
|
|
|
let count = self.parse_anon_const_expr()?;
|
|
|
|
|
let count = self.parse_expr_anon_const()?;
|
|
|
|
|
self.expect(close)?;
|
|
|
|
|
ExprKind::Repeat(first_expr, count)
|
|
|
|
|
} else if self.eat(&token::Comma) {
|
|
|
|
@ -1476,7 +1476,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
self.maybe_recover_from_bad_qpath(expr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let (qself, path) = if self.eat_lt() {
|
|
|
|
|
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
|
|
|
|
|
(Some(qself), path)
|
|
|
|
@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `'label: $expr`. The label is already parsed.
|
|
|
|
|
fn parse_labeled_expr(
|
|
|
|
|
fn parse_expr_labeled(
|
|
|
|
|
&mut self,
|
|
|
|
|
label_: Label,
|
|
|
|
|
mut consume_colon: bool,
|
|
|
|
@ -1522,15 +1522,15 @@ impl<'a> Parser<'a> {
|
|
|
|
|
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)
|
|
|
|
|
self.parse_expr_while(label, lo)
|
|
|
|
|
} else if self.eat_keyword(kw::For) {
|
|
|
|
|
self.parse_for_expr(label, lo)
|
|
|
|
|
self.parse_expr_for(label, lo)
|
|
|
|
|
} else if self.eat_keyword(kw::Loop) {
|
|
|
|
|
self.parse_loop_expr(label, lo)
|
|
|
|
|
self.parse_expr_loop(label, lo)
|
|
|
|
|
} else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
|
|
|
|
|
|| self.token.is_whole_block()
|
|
|
|
|
{
|
|
|
|
|
self.parse_block_expr(label, lo, BlockCheckMode::Default)
|
|
|
|
|
self.parse_expr_block(label, lo, BlockCheckMode::Default)
|
|
|
|
|
} else if !ate_colon
|
|
|
|
|
&& self.may_recover()
|
|
|
|
|
&& (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
|
|
|
|
@ -1670,7 +1670,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `"return" expr?`.
|
|
|
|
|
fn parse_return_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_return(&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);
|
|
|
|
@ -1678,7 +1678,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `"do" "yeet" expr?`.
|
|
|
|
|
fn parse_yeet_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let lo = self.token.span;
|
|
|
|
|
|
|
|
|
|
self.bump(); // `do`
|
|
|
|
@ -1700,13 +1700,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) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let lo = self.prev_token.span;
|
|
|
|
|
let mut label = self.eat_label();
|
|
|
|
|
let kind = if self.token == token::Colon && let Some(label) = label.take() {
|
|
|
|
|
// 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, true)?;
|
|
|
|
|
let lexpr = self.parse_expr_labeled(label, true)?;
|
|
|
|
|
self.sess.emit_err(errors::LabeledLoopInBreak {
|
|
|
|
|
span: lexpr.span,
|
|
|
|
|
sub: errors::WrapExpressionInParentheses {
|
|
|
|
@ -1759,7 +1759,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `"continue" label?`.
|
|
|
|
|
fn parse_continue_expr(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let mut label = self.eat_label();
|
|
|
|
|
|
|
|
|
|
// Recover `continue label` -> `continue 'label`
|
|
|
|
@ -1776,7 +1776,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse `"yield" expr?`.
|
|
|
|
|
fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_yield(&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);
|
|
|
|
@ -1993,7 +1993,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
/// expression.
|
|
|
|
|
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(Delimiter::Brace) {
|
|
|
|
|
match snapshot.parse_expr_array_or_repeat(Delimiter::Brace) {
|
|
|
|
|
Ok(arr) => {
|
|
|
|
|
self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces {
|
|
|
|
|
span: arr.span,
|
|
|
|
@ -2056,7 +2056,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a block or unsafe block.
|
|
|
|
|
pub(super) fn parse_block_expr(
|
|
|
|
|
pub(super) fn parse_expr_block(
|
|
|
|
|
&mut self,
|
|
|
|
|
opt_label: Option<Label>,
|
|
|
|
|
lo: Span,
|
|
|
|
@ -2086,7 +2086,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a closure expression (e.g., `move |args| expr`).
|
|
|
|
|
fn parse_closure_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let lo = self.token.span;
|
|
|
|
|
|
|
|
|
|
let binder = if self.check_keyword(kw::For) {
|
|
|
|
@ -2123,7 +2123,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)?
|
|
|
|
|
self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -2236,9 +2236,9 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses an `if` expression (`if` token already eaten).
|
|
|
|
|
fn parse_if_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let lo = self.prev_token.span;
|
|
|
|
|
let cond = self.parse_cond_expr()?;
|
|
|
|
|
let cond = self.parse_expr_cond()?;
|
|
|
|
|
self.parse_if_after_cond(lo, cond)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2316,12 +2316,12 @@ impl<'a> Parser<'a> {
|
|
|
|
|
self.error_on_if_block_attrs(lo, false, block.span, attrs);
|
|
|
|
|
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_expr_else()?) } else { None };
|
|
|
|
|
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses the condition of a `if` or `while` expression.
|
|
|
|
|
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let cond =
|
|
|
|
|
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
|
|
|
|
|
|
|
|
|
@ -2334,7 +2334,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a `let $pat = $expr` pseudo-expression.
|
|
|
|
|
fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_let(&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.
|
|
|
|
@ -2364,7 +2364,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
self.expect(&token::Eq)?;
|
|
|
|
|
}
|
|
|
|
|
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
|
|
|
|
|
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
|
|
|
|
|
this.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())
|
|
|
|
|
})?;
|
|
|
|
|
let span = lo.to(expr.span);
|
|
|
|
|
self.sess.gated_spans.gate(sym::let_chains, span);
|
|
|
|
@ -2372,11 +2372,11 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses an `else { ... }` expression (`else` token already eaten).
|
|
|
|
|
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let else_span = self.prev_token.span; // `else`
|
|
|
|
|
let attrs = self.parse_outer_attributes()?; // For recovery.
|
|
|
|
|
let expr = if self.eat_keyword(kw::If) {
|
|
|
|
|
self.parse_if_expr()?
|
|
|
|
|
self.parse_expr_if()?
|
|
|
|
|
} else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
|
|
|
|
|
self.parse_simple_block()?
|
|
|
|
|
} else {
|
|
|
|
@ -2450,7 +2450,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) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_for(&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`.
|
|
|
|
@ -2508,8 +2508,8 @@ 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) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let cond = self.parse_cond_expr().map_err(|mut err| {
|
|
|
|
|
fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let cond = self.parse_expr_cond().map_err(|mut err| {
|
|
|
|
|
err.span_label(lo, "while parsing the condition of this `while` expression");
|
|
|
|
|
err
|
|
|
|
|
})?;
|
|
|
|
@ -2526,7 +2526,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses `loop { ... }` (`loop` token already eaten).
|
|
|
|
|
fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
|
|
|
|
let loop_span = self.prev_token.span;
|
|
|
|
|
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
|
|
|
|
Ok(self.mk_expr_with_attrs(
|
|
|
|
@ -2544,7 +2544,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a `match ... { ... }` expression (`match` token already eaten).
|
|
|
|
|
fn parse_match_expr(&mut self) -> PResult<'a, P<Expr>> {
|
|
|
|
|
fn parse_expr_match(&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)?;
|
|
|
|
@ -2914,7 +2914,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
|
|
|
|
|
return Some(Err(err));
|
|
|
|
|
}
|
|
|
|
|
let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
|
|
|
|
|
let expr = self.parse_expr_struct(qself.clone(), 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.sess.emit_err(errors::StructLiteralNotAllowedHere {
|
|
|
|
@ -3043,7 +3043,7 @@ impl<'a> Parser<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Precondition: already parsed the '{'.
|
|
|
|
|
pub(super) fn parse_struct_expr(
|
|
|
|
|
pub(super) fn parse_expr_struct(
|
|
|
|
|
&mut self,
|
|
|
|
|
qself: Option<P<ast::QSelf>>,
|
|
|
|
|
pth: ast::Path,
|
|
|
|
|