@@ -764,30 +764,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
764
764
rhs : & ' tcx hir:: Expr < ' tcx > ,
765
765
span : & Span ,
766
766
) -> Ty < ' tcx > {
767
- let lhs_ty = self . check_expr_with_needs ( & lhs, Needs :: MutPlace ) ;
768
- let rhs_ty = self . check_expr_coercable_to_type ( & rhs, lhs_ty, Some ( lhs) ) ;
769
-
770
767
let expected_ty = expected. coercion_target_type ( self , expr. span ) ;
771
768
if expected_ty == self . tcx . types . bool {
772
769
// The expected type is `bool` but this will result in `()` so we can reasonably
773
770
// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
774
771
// The likely cause of this is `if foo = bar { .. }`.
775
772
let actual_ty = self . tcx . mk_unit ( ) ;
776
773
let mut err = self . demand_suptype_diag ( expr. span , expected_ty, actual_ty) . unwrap ( ) ;
777
- let msg = "try comparing for equality" ;
778
- let left = self . tcx . sess . source_map ( ) . span_to_snippet ( lhs. span ) ;
779
- let right = self . tcx . sess . source_map ( ) . span_to_snippet ( rhs. span ) ;
780
- if let ( Ok ( left) , Ok ( right) ) = ( left, right) {
781
- let help = format ! ( "{} == {}" , left, right) ;
782
- err. span_suggestion ( expr. span , msg, help, Applicability :: MaybeIncorrect ) ;
774
+ let lhs_ty = self . check_expr ( & lhs) ;
775
+ let rhs_ty = self . check_expr ( & rhs) ;
776
+ if self . can_coerce ( lhs_ty, rhs_ty) {
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 : ExprKind :: Match ( _, _, hir:: MatchSource :: IfDesugar { .. } ) ,
781
+ ..
782
+ } ) = self . tcx . hir ( ) . get (
783
+ self . tcx . hir ( ) . get_parent_node ( self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ) ,
784
+ ) {
785
+ // Likely `if let` intended.
786
+ err. span_suggestion_verbose (
787
+ expr. span . shrink_to_lo ( ) ,
788
+ "you might have meant to use pattern matching" ,
789
+ "let " . to_string ( ) ,
790
+ Applicability :: MaybeIncorrect ,
791
+ ) ;
792
+ }
793
+ }
794
+ err. span_suggestion_verbose (
795
+ * span,
796
+ "you might have meant to compare for equality" ,
797
+ "==" . to_string ( ) ,
798
+ Applicability :: MaybeIncorrect ,
799
+ ) ;
783
800
} else {
784
- err. help ( msg) ;
801
+ // Do this to cause extra errors about the assignment.
802
+ let lhs_ty = self . check_expr_with_needs ( & lhs, Needs :: MutPlace ) ;
803
+ let _ = self . check_expr_coercable_to_type ( & rhs, lhs_ty, Some ( lhs) ) ;
785
804
}
786
- err. emit ( ) ;
787
- } else {
788
- self . check_lhs_assignable ( lhs, "E0070" , span) ;
805
+
806
+ if self . sess ( ) . if_let_suggestions . borrow ( ) . get ( & expr. span ) . is_some ( ) {
807
+ // We already emitted an `if let` suggestion due to an identifier not found.
808
+ err. delay_as_bug ( ) ;
809
+ } else {
810
+ err. emit ( ) ;
811
+ }
812
+ return self . tcx . ty_error ( ) ;
789
813
}
790
814
815
+ self . check_lhs_assignable ( lhs, "E0070" , span) ;
816
+
817
+ let lhs_ty = self . check_expr_with_needs ( & lhs, Needs :: MutPlace ) ;
818
+ let rhs_ty = self . check_expr_coercable_to_type ( & rhs, lhs_ty, Some ( lhs) ) ;
819
+
791
820
self . require_type_is_sized ( lhs_ty, lhs. span , traits:: AssignmentLhsSized ) ;
792
821
793
822
if lhs_ty. references_error ( ) || rhs_ty. references_error ( ) {
0 commit comments