diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1b47fa81904..7d753216534 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1131,8 +1131,17 @@ fn check_expr_assign( 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); + let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| { + let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs()); + let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs()); + self.can_coerce(rhs, lhs) + }; let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) { (Applicability::MachineApplicable, true) + } else if refs_can_coerce(rhs_ty, lhs_ty) { + // The lhs and rhs are likely missing some references in either side. Subsequent + // suggestions will show up. + (Applicability::MaybeIncorrect, true) } else if let ExprKind::Binary( Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, _, @@ -1142,7 +1151,11 @@ fn check_expr_assign( // if x == 1 && y == 2 { .. } // + let actual_lhs_ty = self.check_expr(rhs_expr); - (Applicability::MaybeIncorrect, self.can_coerce(rhs_ty, actual_lhs_ty)) + ( + Applicability::MaybeIncorrect, + self.can_coerce(rhs_ty, actual_lhs_ty) + || refs_can_coerce(rhs_ty, actual_lhs_ty), + ) } else if let ExprKind::Binary( Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, lhs_expr, @@ -1152,7 +1165,11 @@ fn check_expr_assign( // if x == 1 && y == 2 { .. } // + let actual_rhs_ty = self.check_expr(lhs_expr); - (Applicability::MaybeIncorrect, self.can_coerce(actual_rhs_ty, lhs_ty)) + ( + Applicability::MaybeIncorrect, + self.can_coerce(actual_rhs_ty, lhs_ty) + || refs_can_coerce(actual_rhs_ty, lhs_ty), + ) } else { (Applicability::MaybeIncorrect, false) }; diff --git a/tests/ui/type/type-check/assignment-expected-bool.rs b/tests/ui/type/type-check/assignment-expected-bool.rs index 191939bdb70..fe8af64b43d 100644 --- a/tests/ui/type/type-check/assignment-expected-bool.rs +++ b/tests/ui/type/type-check/assignment-expected-bool.rs @@ -31,4 +31,9 @@ fn main() { let _: usize = 0 = 0; //~^ ERROR mismatched types [E0308] //~| ERROR invalid left-hand side of assignment [E0070] + + let foo = &String::new(); + let bar = ""; + if foo = bar {} + //~^ ERROR mismatched types [E0308] } diff --git a/tests/ui/type/type-check/assignment-expected-bool.stderr b/tests/ui/type/type-check/assignment-expected-bool.stderr index 56494baff6b..6c44e389a21 100644 --- a/tests/ui/type/type-check/assignment-expected-bool.stderr +++ b/tests/ui/type/type-check/assignment-expected-bool.stderr @@ -135,7 +135,18 @@ LL | let _: usize = 0 = 0; | | | expected due to this -error: aborting due to 13 previous errors +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:37:8 + | +LL | if foo = bar {} + | ^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if foo == bar {} + | + + +error: aborting due to 14 previous errors Some errors have detailed explanations: E0070, E0308. For more information about an error, try `rustc --explain E0070`.