Skip to content

Commit cabf6d0

Browse files
committed
Tweak if let suggestion to be more liberal with suggestion and to not ICE
Fix #77218. Fix #77238.
1 parent 07a63e6 commit cabf6d0

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

802808
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)