Skip to content

Commit

Permalink
Auto merge of rust-lang#77283 - estebank:if-let-sugg, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
Tweak `if let` suggestion to be more liberal with suggestion and to not ICE

Fix rust-lang#77218. Fix rust-lang#77238.
  • Loading branch information
bors committed Oct 26, 2020
2 parents b6ac411 + cabf6d0 commit 16e9ed0
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 34 deletions.
50 changes: 28 additions & 22 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,34 +769,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
let lhs_ty = self.check_expr(&lhs);
let rhs_ty = self.check_expr(&rhs);
if self.can_coerce(lhs_ty, rhs_ty) {
if !lhs.is_syntactic_place_expr() {
// Do not suggest `if let x = y` as `==` is way more likely to be the intention.
if let hir::Node::Expr(hir::Expr {
kind: ExprKind::Match(_, _, hir::MatchSource::IfDesugar { .. }),
..
}) = self.tcx.hir().get(
self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(expr.hir_id)),
) {
// Likely `if let` intended.
err.span_suggestion_verbose(
expr.span.shrink_to_lo(),
"you might have meant to use pattern matching",
"let ".to_string(),
Applicability::MaybeIncorrect,
);
}
let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) {
(Applicability::MachineApplicable, true)
} else {
(Applicability::MaybeIncorrect, false)
};
if !lhs.is_syntactic_place_expr() {
// Do not suggest `if let x = y` as `==` is way more likely to be the intention.
if let hir::Node::Expr(hir::Expr {
kind:
ExprKind::Match(
_,
_,
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar,
),
..
}) = self.tcx.hir().get(
self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(expr.hir_id)),
) {
// Likely `if let` intended.
err.span_suggestion_verbose(
expr.span.shrink_to_lo(),
"you might have meant to use pattern matching",
"let ".to_string(),
applicability,
);
}
}
if eq {
err.span_suggestion_verbose(
*span,
"you might have meant to compare for equality",
"==".to_string(),
Applicability::MaybeIncorrect,
applicability,
);
} else {
// Do this to cause extra errors about the assignment.
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
let _ = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
}

if self.sess().if_let_suggestions.borrow().get(&expr.span).is_some() {
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/issues/issue-77218.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
let value = [7u8];
while Some(0) = value.get(0) { //~ ERROR mismatched types
//~^ NOTE expected `bool`, found `()`
//~| HELP you might have meant to use pattern matching
}
}
14 changes: 14 additions & 0 deletions src/test/ui/issues/issue-77218.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/issue-77218.rs:3:11
|
LL | while Some(0) = value.get(0) {
| ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
help: you might have meant to use pattern matching
|
LL | while let Some(0) = value.get(0) {
| ^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
1 change: 0 additions & 1 deletion src/test/ui/suggestions/if-let-typo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ fn main() {
if Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
if Some(foo) = bar {} //~ ERROR mismatched types
if 3 = foo {} //~ ERROR mismatched types
//~^ ERROR mismatched types
if Some(3) = foo {} //~ ERROR mismatched types
}
18 changes: 7 additions & 11 deletions src/test/ui/suggestions/if-let-typo.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,19 @@ help: you might have meant to compare for equality
LL | if Some(foo) == bar {}
| ^^

error[E0308]: mismatched types
--> $DIR/if-let-typo.rs:6:12
|
LL | if 3 = foo {}
| ^^^ expected integer, found enum `Option`
|
= note: expected type `{integer}`
found enum `Option<{integer}>`

error[E0308]: mismatched types
--> $DIR/if-let-typo.rs:6:8
|
LL | if 3 = foo {}
| ^^^^^^^ expected `bool`, found `()`
|
help: you might have meant to use pattern matching
|
LL | if let 3 = foo {}
| ^^^

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

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

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

0 comments on commit 16e9ed0

Please sign in to comment.