Skip to content

Commit be7032e

Browse files
estebankMark-Simulacrum
authored andcommitted
Tweak if let suggestion to be more liberal with suggestion and to not ICE
Fix #77218. Fix #77238.
1 parent cb3db70 commit be7032e

File tree

5 files changed

+56
-34
lines changed

5 files changed

+56
-34
lines changed

compiler/rustc_typeck/src/check/expr.rs

+28-22
Original file line numberDiff line numberDiff line change
@@ -768,34 +768,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
768768
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
769769
let lhs_ty = self.check_expr(&lhs);
770770
let rhs_ty = self.check_expr(&rhs);
771-
if self.can_coerce(lhs_ty, rhs_ty) {
772-
if !lhs.is_syntactic_place_expr() {
773-
// Do not suggest `if let x = y` as `==` is way more likely to be the intention.
774-
if let hir::Node::Expr(hir::Expr {
775-
kind: ExprKind::Match(_, _, hir::MatchSource::IfDesugar { .. }),
776-
..
777-
}) = self.tcx.hir().get(
778-
self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(expr.hir_id)),
779-
) {
780-
// Likely `if let` intended.
781-
err.span_suggestion_verbose(
782-
expr.span.shrink_to_lo(),
783-
"you might have meant to use pattern matching",
784-
"let ".to_string(),
785-
Applicability::MaybeIncorrect,
786-
);
787-
}
771+
let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) {
772+
(Applicability::MachineApplicable, true)
773+
} else {
774+
(Applicability::MaybeIncorrect, false)
775+
};
776+
if !lhs.is_syntactic_place_expr() {
777+
// Do not suggest `if let x = y` as `==` is way more likely to be the intention.
778+
if let hir::Node::Expr(hir::Expr {
779+
kind:
780+
ExprKind::Match(
781+
_,
782+
_,
783+
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar,
784+
),
785+
..
786+
}) = self.tcx.hir().get(
787+
self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(expr.hir_id)),
788+
) {
789+
// Likely `if let` intended.
790+
err.span_suggestion_verbose(
791+
expr.span.shrink_to_lo(),
792+
"you might have meant to use pattern matching",
793+
"let ".to_string(),
794+
applicability,
795+
);
788796
}
797+
}
798+
if eq {
789799
err.span_suggestion_verbose(
790800
*span,
791801
"you might have meant to compare for equality",
792802
"==".to_string(),
793-
Applicability::MaybeIncorrect,
803+
applicability,
794804
);
795-
} else {
796-
// Do this to cause extra errors about the assignment.
797-
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
798-
let _ = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
799805
}
800806

801807
if self.sess().if_let_suggestions.borrow().get(&expr.span).is_some() {

src/test/ui/issues/issue-77218.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let value = [7u8];
3+
while Some(0) = value.get(0) { //~ ERROR mismatched types
4+
//~^ NOTE expected `bool`, found `()`
5+
//~| HELP you might have meant to use pattern matching
6+
}
7+
}

src/test/ui/issues/issue-77218.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-77218.rs:3:11
3+
|
4+
LL | while Some(0) = value.get(0) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
6+
|
7+
help: you might have meant to use pattern matching
8+
|
9+
LL | while let Some(0) = value.get(0) {
10+
| ^^^
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/suggestions/if-let-typo.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ fn main() {
44
if Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
55
if Some(foo) = bar {} //~ ERROR mismatched types
66
if 3 = foo {} //~ ERROR mismatched types
7-
//~^ ERROR mismatched types
87
if Some(3) = foo {} //~ ERROR mismatched types
98
}

src/test/ui/suggestions/if-let-typo.stderr

+7-11
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,19 @@ help: you might have meant to compare for equality
2424
LL | if Some(foo) == bar {}
2525
| ^^
2626

27-
error[E0308]: mismatched types
28-
--> $DIR/if-let-typo.rs:6:12
29-
|
30-
LL | if 3 = foo {}
31-
| ^^^ expected integer, found enum `Option`
32-
|
33-
= note: expected type `{integer}`
34-
found enum `Option<{integer}>`
35-
3627
error[E0308]: mismatched types
3728
--> $DIR/if-let-typo.rs:6:8
3829
|
3930
LL | if 3 = foo {}
4031
| ^^^^^^^ expected `bool`, found `()`
32+
|
33+
help: you might have meant to use pattern matching
34+
|
35+
LL | if let 3 = foo {}
36+
| ^^^
4137

4238
error[E0308]: mismatched types
43-
--> $DIR/if-let-typo.rs:8:8
39+
--> $DIR/if-let-typo.rs:7:8
4440
|
4541
LL | if Some(3) = foo {}
4642
| ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -54,7 +50,7 @@ help: you might have meant to compare for equality
5450
LL | if Some(3) == foo {}
5551
| ^^
5652

57-
error: aborting due to 5 previous errors
53+
error: aborting due to 4 previous errors
5854

5955
Some errors have detailed explanations: E0308, E0425.
6056
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)