diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 4c7ce30097c..1df5bf1a220 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -54,6 +54,9 @@ parser_invalid_logical_operator = `{$incorrect}` is not a logical operator parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator .suggestion = use `!` to perform bitwise not +parser_unexpected_if_with_if = unexpected `if` in the condition expression + .suggestion = remove the `if` + parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier parser_unexpected_token_after_not_bitwise = use `!` to perform bitwise not parser_unexpected_token_after_not_logical = use `!` to perform logical negation diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 724d92254a4..211450250fd 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1219,3 +1219,11 @@ pub(crate) struct FnPtrWithGenericsSugg { pub arity: usize, pub for_param_list_exists: bool, } + +#[derive(Diagnostic)] +#[diag(parser_unexpected_if_with_if)] +pub(crate) struct UnexpectedIfWithIf( + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")] + pub Span, +); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c9629ea49e0..634e45c8480 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,8 +21,8 @@ NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, - StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, - UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, + StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf, + UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, }; use crate::maybe_recover_from_interpolated_ty_qpath; use core::mem; @@ -2231,6 +2231,7 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P) -> PResult<'a, P< if let Some(block) = recover_block_from_condition(self) { block } else { + self.error_on_extra_if(&cond)?; // Parse block, which will always fail, but we can add a nice note to the error self.parse_block().map_err(|mut err| { err.span_note( @@ -2367,6 +2368,16 @@ fn error_on_if_block_attrs( }); } + fn error_on_extra_if(&mut self, cond: &P) -> 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(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo())))) + } else { + Ok(()) + } + } + /// Parses `for in ` (`for` token already eaten). fn parse_for_expr(&mut self, opt_label: Option