@@ -90,7 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
90
90
self . check_expr_return ( expr_opt. deref ( ) , expr)
91
91
}
92
92
ExprKind :: Assign ( ref lhs, ref rhs) => {
93
- self . check_assign ( expr, expected, lhs, rhs)
93
+ self . check_expr_assign ( expr, expected, lhs, rhs)
94
94
}
95
95
ExprKind :: While ( ref cond, ref body, _) => {
96
96
let ctxt = BreakableCtxt {
@@ -742,4 +742,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
742
742
}
743
743
self . tcx . types . never
744
744
}
745
+
746
+ /// Type check assignment expression `expr` of form `lhs = rhs`.
747
+ /// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
748
+ fn check_expr_assign (
749
+ & self ,
750
+ expr : & ' tcx hir:: Expr ,
751
+ expected : Expectation < ' tcx > ,
752
+ lhs : & ' tcx hir:: Expr ,
753
+ rhs : & ' tcx hir:: Expr ,
754
+ ) -> Ty < ' tcx > {
755
+ let lhs_ty = self . check_expr_with_needs ( & lhs, Needs :: MutPlace ) ;
756
+ let rhs_ty = self . check_expr_coercable_to_type ( & rhs, lhs_ty) ;
757
+
758
+ let expected_ty = expected. coercion_target_type ( self , expr. span ) ;
759
+ if expected_ty == self . tcx . types . bool {
760
+ // The expected type is `bool` but this will result in `()` so we can reasonably
761
+ // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
762
+ // The likely cause of this is `if foo = bar { .. }`.
763
+ let actual_ty = self . tcx . mk_unit ( ) ;
764
+ let mut err = self . demand_suptype_diag ( expr. span , expected_ty, actual_ty) . unwrap ( ) ;
765
+ let msg = "try comparing for equality" ;
766
+ let left = self . tcx . sess . source_map ( ) . span_to_snippet ( lhs. span ) ;
767
+ let right = self . tcx . sess . source_map ( ) . span_to_snippet ( rhs. span ) ;
768
+ if let ( Ok ( left) , Ok ( right) ) = ( left, right) {
769
+ let help = format ! ( "{} == {}" , left, right) ;
770
+ err. span_suggestion ( expr. span , msg, help, Applicability :: MaybeIncorrect ) ;
771
+ } else {
772
+ err. help ( msg) ;
773
+ }
774
+ err. emit ( ) ;
775
+ } else if !lhs. is_place_expr ( ) {
776
+ struct_span_err ! ( self . tcx. sess, expr. span, E0070 ,
777
+ "invalid left-hand side expression" )
778
+ . span_label ( expr. span , "left-hand of expression not valid" )
779
+ . emit ( ) ;
780
+ }
781
+
782
+ self . require_type_is_sized ( lhs_ty, lhs. span , traits:: AssignmentLhsSized ) ;
783
+
784
+ if lhs_ty. references_error ( ) || rhs_ty. references_error ( ) {
785
+ self . tcx . types . err
786
+ } else {
787
+ self . tcx . mk_unit ( )
788
+ }
789
+ }
745
790
}
0 commit comments