Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 40 additions & 13 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2760,9 +2760,13 @@ impl<'a> Parser<'a> {
let (mut cond, _) =
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;

CondChecker::new(self, let_chains_policy).visit_expr(&mut cond);

Ok(cond)
let mut checker = CondChecker::new(self, let_chains_policy);
checker.visit_expr(&mut cond);
Ok(if let Some(guar) = checker.found_incorrect_let_chain {
self.mk_expr_err(cond.span, guar)
} else {
cond
})
}

/// Parses a `let $pat = $expr` pseudo-expression.
Expand Down Expand Up @@ -3484,13 +3488,19 @@ impl<'a> Parser<'a> {
let if_span = self.prev_token.span;
let mut cond = self.parse_match_guard_condition()?;

CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
let mut checker = CondChecker::new(self, LetChainsPolicy::AlwaysAllowed);
checker.visit_expr(&mut cond);

if has_let_expr(&cond) {
let span = if_span.to(cond.span);
self.psess.gated_spans.gate(sym::if_let_guard, span);
}
Ok(Some(cond))

Ok(Some(if let Some(guar) = checker.found_incorrect_let_chain {
self.mk_expr_err(cond.span, guar)
} else {
cond
}))
}

fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr>>)> {
Expand All @@ -3511,13 +3521,23 @@ impl<'a> Parser<'a> {
let ast::PatKind::Paren(subpat) = pat.kind else { unreachable!() };
let ast::PatKind::Guard(_, mut cond) = subpat.kind else { unreachable!() };
self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
let mut checker = CondChecker::new(self, LetChainsPolicy::AlwaysAllowed);
checker.visit_expr(&mut cond);

let right = self.prev_token.span;
self.dcx().emit_err(errors::ParenthesesInMatchPat {
span: vec![left, right],
sugg: errors::ParenthesesInMatchPatSugg { left, right },
});
Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond)))

Ok((
self.mk_pat(span, ast::PatKind::Wild),
(if let Some(guar) = checker.found_incorrect_let_chain {
Some(self.mk_expr_err(cond.span, guar))
} else {
Some(cond)
}),
))
} else {
Ok((pat, self.parse_match_arm_guard()?))
}
Expand Down Expand Up @@ -4208,6 +4228,7 @@ struct CondChecker<'a> {
forbid_let_reason: Option<ForbiddenLetReason>,
missing_let: Option<errors::MaybeMissingLet>,
comparison: Option<errors::MaybeComparison>,
found_incorrect_let_chain: Option<ErrorGuaranteed>,
}

impl<'a> CondChecker<'a> {
Expand All @@ -4218,6 +4239,7 @@ impl<'a> CondChecker<'a> {
missing_let: None,
comparison: None,
let_chains_policy,
found_incorrect_let_chain: None,
depth: 0,
}
}
Expand All @@ -4236,12 +4258,17 @@ impl MutVisitor for CondChecker<'_> {
NotSupportedOr(or_span) => {
self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span })
}
_ => self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet {
span,
reason,
missing_let: self.missing_let,
comparison: self.comparison,
}),
_ => {
let guar =
self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet {
span,
reason,
missing_let: self.missing_let,
comparison: self.comparison,
});
self.found_incorrect_let_chain = Some(guar);
guar
}
};
*recovered = Recovered::Yes(error);
} else if self.depth > 1 {
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/expr/if/bad-if-let-suggestion.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
fn a() {
if let x = 1 && i = 2 {}
//~^ ERROR cannot find value `i` in this scope
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
//~^ ERROR expected expression, found `let` statement
}

fn b() {
Expand Down
30 changes: 6 additions & 24 deletions tests/ui/expr/if/bad-if-let-suggestion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ LL | if let x = 1 && i == 2 {}
| +

error[E0425]: cannot find value `i` in this scope
--> $DIR/bad-if-let-suggestion.rs:2:21
|
LL | if let x = 1 && i = 2 {}
| ^ not found in this scope

error[E0425]: cannot find value `i` in this scope
--> $DIR/bad-if-let-suggestion.rs:9:9
--> $DIR/bad-if-let-suggestion.rs:7:9
|
LL | fn a() {
| ------ similarly named function `a` defined here
Expand All @@ -36,7 +30,7 @@ LL + if (a + j) = i {}
|

error[E0425]: cannot find value `j` in this scope
--> $DIR/bad-if-let-suggestion.rs:9:13
--> $DIR/bad-if-let-suggestion.rs:7:13
|
LL | fn a() {
| ------ similarly named function `a` defined here
Expand All @@ -51,7 +45,7 @@ LL + if (i + a) = i {}
|

error[E0425]: cannot find value `i` in this scope
--> $DIR/bad-if-let-suggestion.rs:9:18
--> $DIR/bad-if-let-suggestion.rs:7:18
|
LL | fn a() {
| ------ similarly named function `a` defined here
Expand All @@ -66,7 +60,7 @@ LL + if (i + j) = a {}
|

error[E0425]: cannot find value `x` in this scope
--> $DIR/bad-if-let-suggestion.rs:16:8
--> $DIR/bad-if-let-suggestion.rs:14:8
|
LL | fn a() {
| ------ similarly named function `a` defined here
Expand All @@ -80,18 +74,6 @@ LL - if x[0] = 1 {}
LL + if a[0] = 1 {}
|

error[E0308]: mismatched types
--> $DIR/bad-if-let-suggestion.rs:2:8
|
LL | if let x = 1 && i = 2 {}
| ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
help: you might have meant to compare for equality
|
LL | if let x = 1 && i == 2 {}
| +

error: aborting due to 7 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0308, E0425.
For more information about an error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0425`.
36 changes: 0 additions & 36 deletions tests/ui/parser/let-chains-assign-add-incorrect.fixed

This file was deleted.

14 changes: 0 additions & 14 deletions tests/ui/parser/let-chains-assign-add-incorrect.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@ edition:2024
//@ run-rustfix

#![allow(irrefutable_let_patterns)]

Expand All @@ -8,26 +7,13 @@ fn test_where_left_is_not_let() {
if let _ = 1 && true && y += 2 {};
//~^ ERROR expected expression, found `let` statement
//~| NOTE only supported directly in conditions of `if` and `while` expressions
//~| ERROR mismatched types
//~| NOTE expected `bool`, found integer
//~| NOTE you are add-assigning the right-hand side expression to the result of this let-chain
//~| NOTE expected because this is `bool`
//~| ERROR binary assignment operation `+=` cannot be used in a let chain
//~| NOTE cannot use `+=` in a let chain
//~| HELP you might have meant to compare with `==` instead of assigning with `+=`
}

fn test_where_left_is_let() {
let y = 2;
if let _ = 1 && y += 2 {};
//~^ ERROR expected expression, found `let` statement
//~| NOTE only supported directly in conditions of `if` and `while` expressions
//~| ERROR mismatched types
//~| NOTE expected `bool`, found integer
//~| NOTE you are add-assigning the right-hand side expression to the result of this let-chain
//~| ERROR binary assignment operation `+=` cannot be used in a let chain
//~| NOTE cannot use `+=` in a let chain
//~| HELP you might have meant to compare with `==` instead of assigning with `+=`
}

fn main() {
Expand Down
49 changes: 3 additions & 46 deletions tests/ui/parser/let-chains-assign-add-incorrect.stderr
Original file line number Diff line number Diff line change
@@ -1,61 +1,18 @@
error: expected expression, found `let` statement
--> $DIR/let-chains-assign-add-incorrect.rs:8:8
--> $DIR/let-chains-assign-add-incorrect.rs:7:8
|
LL | if let _ = 1 && true && y += 2 {};
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions

error: expected expression, found `let` statement
--> $DIR/let-chains-assign-add-incorrect.rs:22:8
--> $DIR/let-chains-assign-add-incorrect.rs:14:8
|
LL | if let _ = 1 && y += 2 {};
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions

error[E0308]: mismatched types
--> $DIR/let-chains-assign-add-incorrect.rs:8:29
|
LL | if let _ = 1 && true && y += 2 {};
| ----------------- ^ expected `bool`, found integer
| |
| expected because this is `bool`

error: binary assignment operation `+=` cannot be used in a let chain
--> $DIR/let-chains-assign-add-incorrect.rs:8:31
|
LL | if let _ = 1 && true && y += 2 {};
| ---------------------- ^^ cannot use `+=` in a let chain
| |
| you are add-assigning the right-hand side expression to the result of this let-chain
|
help: you might have meant to compare with `==` instead of assigning with `+=`
|
LL - if let _ = 1 && true && y += 2 {};
LL + if let _ = 1 && true && y == 2 {};
|

error[E0308]: mismatched types
--> $DIR/let-chains-assign-add-incorrect.rs:22:21
|
LL | if let _ = 1 && y += 2 {};
| ^ expected `bool`, found integer

error: binary assignment operation `+=` cannot be used in a let chain
--> $DIR/let-chains-assign-add-incorrect.rs:22:23
|
LL | if let _ = 1 && y += 2 {};
| -------------- ^^ cannot use `+=` in a let chain
| |
| you are add-assigning the right-hand side expression to the result of this let-chain
|
help: you might have meant to compare with `==` instead of assigning with `+=`
|
LL - if let _ = 1 && y += 2 {};
LL + if let _ = 1 && y == 2 {};
|

error: aborting due to 6 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
Loading
Loading