From cabf6d052329c8ba5f23c7fc4873e9db64874997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2020 18:58:56 -0700 Subject: [PATCH] Tweak `if let` suggestion to be more liberal with suggestion and to not ICE Fix #77218. Fix #77238. --- compiler/rustc_typeck/src/check/expr.rs | 50 ++++++++++++---------- src/test/ui/issues/issue-77218.rs | 7 +++ src/test/ui/issues/issue-77218.stderr | 14 ++++++ src/test/ui/suggestions/if-let-typo.rs | 1 - src/test/ui/suggestions/if-let-typo.stderr | 18 +++----- 5 files changed, 56 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/issues/issue-77218.rs create mode 100644 src/test/ui/issues/issue-77218.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 9990f86a36b13..03e448a00cc77 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -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() { diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs new file mode 100644 index 0000000000000..bc992c21dca5c --- /dev/null +++ b/src/test/ui/issues/issue-77218.rs @@ -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 + } +} diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr new file mode 100644 index 0000000000000..eca44725eb258 --- /dev/null +++ b/src/test/ui/issues/issue-77218.stderr @@ -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`. diff --git a/src/test/ui/suggestions/if-let-typo.rs b/src/test/ui/suggestions/if-let-typo.rs index c1e417b97f619..87def13c476c7 100644 --- a/src/test/ui/suggestions/if-let-typo.rs +++ b/src/test/ui/suggestions/if-let-typo.rs @@ -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 } diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index bb2ea8cb4778a..d8e50cae55ad1 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -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`.