diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2023-12-26 21:14:58 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2023-12-26 23:48:55 +0000 |
| commit | dc30eb19677a3dd178660ce6f903c3d0a18c847d (patch) | |
| tree | 9fccd1f71e64f1f6dbcc5eeaca1ef1fc6de33d09 | |
| parent | 2df6406b886757a3c1475957660a3a4ae6c786de (diff) | |
| download | rust-dc30eb19677a3dd178660ce6f903c3d0a18c847d.tar.gz rust-dc30eb19677a3dd178660ce6f903c3d0a18c847d.zip | |
Suggest `=` to `==` in more cases, even in the face of reference mismatch
Given `foo: &String` and `bar: str`, suggest `==` when given `if foo = bar {}`:
```
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 {}
| +
```
| -rw-r--r-- | compiler/rustc_hir_typeck/src/expr.rs | 21 | ||||
| -rw-r--r-- | tests/ui/type/type-check/assignment-expected-bool.rs | 5 | ||||
| -rw-r--r-- | tests/ui/type/type-check/assignment-expected-bool.stderr | 13 |
3 files changed, 36 insertions, 3 deletions
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 @@ 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); + 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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`. |
