diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser/expr.rs')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 82 |
1 files changed, 49 insertions, 33 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1d883e16f9d..44cb90227e7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1007,8 +1007,9 @@ impl<'a> Parser<'a> { let span = self.token.span; let sm = self.sess.source_map(); let (span, actual) = match (&self.token.kind, self.subparser_name) { - (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => - (span.shrink_to_hi(), actual.into()), + (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => { + (span.shrink_to_hi(), actual.into()) + } _ => (span, actual), }; self.sess.emit_err(errors::UnexpectedTokenAfterDot { span, actual }); @@ -1550,10 +1551,7 @@ impl<'a> Parser<'a> { self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span)); } let lo = path.span; - let mac = P(MacCall { - path, - args: self.parse_delim_args()?, - }); + let mac = P(MacCall { path, args: self.parse_delim_args()? }); (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, &path) @@ -1771,7 +1769,9 @@ impl<'a> Parser<'a> { 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() { + 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_expr_labeled(label, true)?; @@ -2209,6 +2209,7 @@ impl<'a> Parser<'a> { fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> { let lo = self.token.span; + let before = self.prev_token.clone(); let binder = if self.check_keyword(kw::For) { let lo = self.token.span; let lifetime_defs = self.parse_late_bound_lifetime_defs()?; @@ -2239,7 +2240,12 @@ impl<'a> Parser<'a> { FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET; - self.parse_expr_res(restrictions, None)? + let prev = self.prev_token.clone(); + let token = self.token.clone(); + match self.parse_expr_res(restrictions, None) { + Ok(expr) => expr, + Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?, + } } _ => { // If an explicit return type is given, require a block to appear (RFC 968). @@ -2371,16 +2377,18 @@ impl<'a> Parser<'a> { let mut recover_block_from_condition = |this: &mut Self| { let block = match &mut cond.kind { ExprKind::Binary(Spanned { span: binop_span, .. }, _, right) - if let ExprKind::Block(_, None) = right.kind => { - self.sess.emit_err(errors::IfExpressionMissingThenBlock { - if_span: lo, - missing_then_block_sub: - errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)), - let_else_sub: None, - - }); - std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) - }, + if let ExprKind::Block(_, None) = right.kind => + { + self.sess.emit_err(errors::IfExpressionMissingThenBlock { + if_span: lo, + missing_then_block_sub: + errors::IfExpressionMissingThenBlockSub::UnfinishedCondition( + cond_span.shrink_to_lo().to(*binop_span), + ), + let_else_sub: None, + }); + std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) + } ExprKind::Block(_, None) => { self.sess.emit_err(errors::IfExpressionMissingCondition { if_span: lo.shrink_to_hi(), @@ -2459,10 +2467,16 @@ impl<'a> Parser<'a> { /// Parses a `let $pat = $expr` pseudo-expression. fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> { let is_recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { - Some(self.sess.emit_err(errors::ExpectedExpressionFoundLet { + let err = errors::ExpectedExpressionFoundLet { span: self.token.span, reason: ForbiddenLetReason::OtherForbidden, - })) + }; + if self.prev_token.kind == token::BinOp(token::Or) { + // This was part of a closure, the that part of the parser recover. + return Err(err.into_diagnostic(&self.sess.span_diagnostic)); + } else { + Some(self.sess.emit_err(err)) + } } else { None }; @@ -2557,13 +2571,16 @@ impl<'a> Parser<'a> { } fn error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()> { - if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind && - let BinOpKind::And = binop && - let ExprKind::If(cond, ..) = &right.kind { - Err(self.sess.create_err(errors::UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo())))) - } else { - Ok(()) - } + if let ExprKind::Binary(Spanned { span: binop_span, node: binop }, _, right) = &cond.kind + && let BinOpKind::And = binop + && let ExprKind::If(cond, ..) = &right.kind + { + Err(self.sess.create_err(errors::UnexpectedIfWithIf( + binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()), + ))) + } else { + Ok(()) + } } /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). @@ -2911,9 +2928,9 @@ impl<'a> Parser<'a> { .or_else(|mut err| { if this.token == token::FatArrow { if let Ok(expr_lines) = sm.span_to_lines(expr.span) - && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) - && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col - && expr_lines.lines.len() == 2 + && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) + && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col + && expr_lines.lines.len() == 2 { // We check whether there's any trailing code in the parse span, // if there isn't, we very likely have the following: @@ -3169,7 +3186,7 @@ impl<'a> Parser<'a> { e.span_suggestion_verbose( self.token.span.shrink_to_lo(), "try naming a field", - &format!("{ident}: ", ), + &format!("{ident}: ",), Applicability::MaybeIncorrect, ); } @@ -3562,8 +3579,7 @@ impl MutVisitor for CondChecker<'_> { noop_visit_expr(e, self); self.forbid_let_reason = forbid_let_reason; } - ExprKind::Cast(ref mut op, _) - | ExprKind::Type(ref mut op, _) => { + ExprKind::Cast(ref mut op, _) | ExprKind::Type(ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; self.forbid_let_reason = Some(OtherForbidden); self.visit_expr(op); |
