diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser/expr.rs')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 42 | 
1 files changed, 34 insertions, 8 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 577003e94fb..d2d21624150 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -45,7 +45,7 @@ use thin_vec::{thin_vec, ThinVec}; macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = &$p.token.kind { - match &nt.0 { + match &**nt { token::NtExpr(e) | token::NtLiteral(e) => { let e = e.clone(); $p.bump(); @@ -497,8 +497,7 @@ impl<'a> Parser<'a> { /// Checks if this expression is a successfully parsed statement. fn expr_is_complete(&self, e: &Expr) -> bool { - self.restrictions.contains(Restrictions::STMT_EXPR) - && !classify::expr_requires_semi_to_be_stmt(e) + self.restrictions.contains(Restrictions::STMT_EXPR) && classify::expr_is_complete(e) } /// Parses `x..y`, `x..=y`, and `x..`/`x..=`. @@ -725,7 +724,9 @@ impl<'a> Parser<'a> { /// Returns the span of expr if it was not interpolated, or the span of the interpolated token. fn interpolated_or_expr_span(&self, expr: &Expr) -> Span { match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_token.span, + TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => { + self.prev_token.span + } _ => expr.span, } } @@ -2691,8 +2692,33 @@ impl<'a> Parser<'a> { let first_tok_span = self.token.span; match self.parse_expr() { Ok(cond) - // If it's not a free-standing expression, and is followed by a block, - // then it's very likely the condition to an `else if`. + // Try to guess the difference between a "condition-like" vs + // "statement-like" expression. + // + // We are seeing the following code, in which $cond is neither + // ExprKind::Block nor ExprKind::If (the 2 cases wherein this + // would be valid syntax). + // + // if ... { + // } else $cond + // + // If $cond is "condition-like" such as ExprKind::Binary, we + // want to suggest inserting `if`. + // + // if ... { + // } else if a == b { + // ^^ + // } + // + // If $cond is "statement-like" such as ExprKind::While then we + // want to suggest wrapping in braces. + // + // if ... { + // } else { + // ^ + // while true {} + // } + // ^ if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) && classify::expr_requires_semi_to_be_stmt(&cond) => { @@ -3136,7 +3162,7 @@ impl<'a> Parser<'a> { err })?; - let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) + let require_comma = !classify::expr_is_complete(&expr) && this.token != token::CloseDelim(Delimiter::Brace); if !require_comma { @@ -3708,7 +3734,7 @@ impl<'a> Parser<'a> { /// Parses `ident (COLON expr)?`. fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; - self.recover_diff_marker(); + self.recover_vcs_conflict_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span;  | 
