Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. --Given the following code: The current output is: <!-- The following is not always necessary. --Ideally the output should suggest removing the additional keyword in front of the . This mistake can occur due to muscle memory as , , and in the future are somewhat similar syntactically. Thanks. label +D-confusing +F-let-else <!-- If the problem is not self-explanatory, please provide a rationale for the change. --<!-- If dramatically different output is caused by small changes, consider also adding them here. If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition. --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I think the current suggestion is valid. Because one writes instead of writing . So the suggestion if changed maybe fall-negative.
We should likely add an alternative suggestion to remove the , but keep both. I think that the current suggestion is likely going to be the more common situation, so it should still come first.
claim
What would be the best way to go about adding an alternate suggestion? I'd like to try my hand at this. What I think needs to be done is adding help text to , add a variant to , and then add something to to add the alternate after the primary suggestion. Is this a good starting point?
it sounds like you are in the right path.
I looked a bit into this issue and have already found where to add text to the and the as mentioned, but i am a bit overwhelmed how and where to start in the in the . Does anyone have a hint for me?
claim
claim
You can add instructions in the parser to track your progress. I'm not sure about the specifics out of the top of my head here of what type each step in the parse is, but you will have successfully parsed the , the condition and then you'll encounter an token when a body/block was expected. That's where the new recovery should kick in, pointing at the span saying that you might want to remove it.
claim

Discussion:
parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else` parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed <ins> parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement </ins> parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable .suggestion = initialize the variable

#[primary_span] pub if_span: Span, #[subdiagnostic] <del> pub sub: IfExpressionMissingThenBlockSub, </del> <ins> pub missing_then_block_sub: IfExpressionMissingThenBlockSub, #[subdiagnostic] pub let_else_sub: Option<IfExpressionLetSomeSub>, </ins> } #[derive(Subdiagnostic)]

AddThenBlock(#[primary_span] Span), } <ins> #[derive(Subdiagnostic)] #[help(parse_extra_if_in_let_else)] pub(crate) struct IfExpressionLetSomeSub { #[primary_span] pub if_span: Span, } </ins> #[derive(Diagnostic)] #[diag(parse_if_expression_missing_condition)] pub(crate) struct IfExpressionMissingCondition {

ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, <del> IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, </del> <ins> IfExpressionLetSomeSub, IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, </ins> RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf, UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,

if let ExprKind::Block(_, None) = right.kind => { self.sess.emit_err(IfExpressionMissingThenBlock { if_span: lo, <del> sub: IfExpressionMissingThenBlockSub::UnfinishedCondition( cond_span.shrink_to_lo().to(*binop_span) ), </del> <ins> missing_then_block_sub: IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)), let_else_sub: None, </ins> }); std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) },

if let Some(block) = recover_block_from_condition(self) { block } else { <ins> let let_else_sub = matches!(cond.kind, ExprKind::Let(..)) .then(|| IfExpressionLetSomeSub { if_span: lo }); </ins> self.sess.emit_err(IfExpressionMissingThenBlock { if_span: lo, <del> sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()), </del> <ins> missing_then_block_sub: IfExpressionMissingThenBlockSub::AddThenBlock( cond_span.shrink_to_hi(), ), let_else_sub, </ins> }); self.mk_block_err(cond_span.shrink_to_hi()) }

<ins> fn main() { let x = Some(123); if let Some(y) = x else { //~ ERROR this `if` expression is missing a block return; }; } </ins>

<ins> error: this `if` expression is missing a block after the condition --> $DIR/accidental-if.rs:3:5 | LL |     if let Some(y) = x else { |     ^^ | help: add a block here --> $DIR/accidental-if.rs:3:23 | LL |     if let Some(y) = x else { |                       ^ help: remove the `if` if you meant to write a `let...else` statement --> $DIR/accidental-if.rs:3:5 | LL |     if let Some(y) = x else { |     ^^ error: aborting due to previous error </ins>

| LL |     if let Some(n) = opt else { |                         ^ <ins> help: remove the `if` if you meant to write a `let...else` statement --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:5 | LL |     if let Some(n) = opt else { |     ^^ </ins> error: this `if` expression is missing a block after the condition --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5