Tweak if let suggestion to be more liberal with suggestion and to not ICE

Fix #77218. Fix #77238.
This commit is contained in:
Esteban Küber 2020-09-27 18:58:56 -07:00
parent 07a63e6d1f
commit cabf6d0523
5 changed files with 56 additions and 34 deletions

View File

@ -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() {

View File

@ -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
}
}

View File

@ -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`.

View File

@ -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
}

View File

@ -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 `()`
@ -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`.