diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 8b08c7b68b784..1e9986fa761c4 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -34,19 +34,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let (lhs_ty, rhs_ty, return_ty) = + let (lhs_ty, rhs_ty, _return_ty) = self.check_overloaded_binop(expr, lhs, rhs, Op::AssignOp(op), expected); let category = BinOpCategory::from(op.node); - let ty = if !lhs_ty.is_ty_var() - && !rhs_ty.is_ty_var() - && is_builtin_binop(lhs_ty, rhs_ty, category) + if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, category) { self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, category); - self.tcx.types.unit - } else { - return_ty - }; + } self.check_lhs_assignable(lhs, E0067, op.span, |err| { if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { @@ -86,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }); - ty + self.tcx.types.unit } /// Checks a potentially overloaded binary operator. @@ -1311,21 +1306,16 @@ fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> { } /// Returns `true` if this is a built-in arithmetic operation (e.g., -/// u32 + u32, i16x4 == i16x4) and false if these types would have to be -/// overloaded to be legal. There are two reasons that we distinguish +/// u32 + u32) and false if these types would have to be +/// overloaded to be legal. The reason that we distinguish /// builtin operations from overloaded ones (vs trying to drive /// everything uniformly through the trait system and intrinsics or -/// something like that): -/// -/// 1. Builtin operations can trivially be evaluated in constants. -/// 2. For comparison operators applied to SIMD types the result is -/// not of type `bool`. For example, `i16x4 == i16x4` yields a -/// type like `i16x4`. This means that the overloaded trait -/// `PartialEq` is not applicable. +/// something like that) is that builtin operations can trivially +/// be evaluated in constants on stable, but the traits and their +/// impls for these primitive types. /// -/// Reason #2 is the killer. I tried for a while to always use -/// overloaded logic and just check the types in constants/codegen after -/// the fact, and it worked fine, except for SIMD types. -nmatsakis +/// FIXME(const_trait_impls): once the traits and their impls are const stable +/// remove this function and the builtin-specific checks. fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, category: BinOpCategory) -> bool { // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // (See https://github.com/rust-lang/rust/issues/57447.) diff --git a/tests/ui/parser/let-chains-assign-add-incorrect.fixed b/tests/ui/parser/let-chains-assign-add-incorrect.fixed index b1abce8bd2df5..469c78bb6939c 100644 --- a/tests/ui/parser/let-chains-assign-add-incorrect.fixed +++ b/tests/ui/parser/let-chains-assign-add-incorrect.fixed @@ -15,6 +15,8 @@ fn test_where_left_is_not_let() { //~| ERROR binary assignment operation `+=` cannot be used in a let chain //~| NOTE cannot use `+=` in a let chain //~| HELP you might have meant to compare with `==` instead of assigning with `+=` + //~| ERROR mismatched types + //~| NOTE expected `bool`, found `()` } fn test_where_left_is_let() { @@ -28,6 +30,8 @@ fn test_where_left_is_let() { //~| ERROR binary assignment operation `+=` cannot be used in a let chain //~| NOTE cannot use `+=` in a let chain //~| HELP you might have meant to compare with `==` instead of assigning with `+=` + //~| ERROR mismatched types + //~| NOTE expected `bool`, found `()` } fn main() { diff --git a/tests/ui/parser/let-chains-assign-add-incorrect.rs b/tests/ui/parser/let-chains-assign-add-incorrect.rs index 3b2e5e93d91ac..6bdb4b648ebad 100644 --- a/tests/ui/parser/let-chains-assign-add-incorrect.rs +++ b/tests/ui/parser/let-chains-assign-add-incorrect.rs @@ -15,6 +15,8 @@ fn test_where_left_is_not_let() { //~| ERROR binary assignment operation `+=` cannot be used in a let chain //~| NOTE cannot use `+=` in a let chain //~| HELP you might have meant to compare with `==` instead of assigning with `+=` + //~| ERROR mismatched types + //~| NOTE expected `bool`, found `()` } fn test_where_left_is_let() { @@ -28,6 +30,8 @@ fn test_where_left_is_let() { //~| ERROR binary assignment operation `+=` cannot be used in a let chain //~| NOTE cannot use `+=` in a let chain //~| HELP you might have meant to compare with `==` instead of assigning with `+=` + //~| ERROR mismatched types + //~| NOTE expected `bool`, found `()` } fn main() { diff --git a/tests/ui/parser/let-chains-assign-add-incorrect.stderr b/tests/ui/parser/let-chains-assign-add-incorrect.stderr index dea8e6a1982b1..02926965edd0e 100644 --- a/tests/ui/parser/let-chains-assign-add-incorrect.stderr +++ b/tests/ui/parser/let-chains-assign-add-incorrect.stderr @@ -7,7 +7,7 @@ LL | if let _ = 1 && true && y += 2 {}; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/let-chains-assign-add-incorrect.rs:22:8 + --> $DIR/let-chains-assign-add-incorrect.rs:24:8 | LL | if let _ = 1 && y += 2 {}; | ^^^^^^^^^ @@ -37,13 +37,19 @@ LL + if let _ = 1 && true && y == 2 {}; | error[E0308]: mismatched types - --> $DIR/let-chains-assign-add-incorrect.rs:22:21 + --> $DIR/let-chains-assign-add-incorrect.rs:8:8 + | +LL | if let _ = 1 && true && y += 2 {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + +error[E0308]: mismatched types + --> $DIR/let-chains-assign-add-incorrect.rs:24:21 | LL | if let _ = 1 && y += 2 {}; | ^ expected `bool`, found integer error: binary assignment operation `+=` cannot be used in a let chain - --> $DIR/let-chains-assign-add-incorrect.rs:22:23 + --> $DIR/let-chains-assign-add-incorrect.rs:24:23 | LL | if let _ = 1 && y += 2 {}; | -------------- ^^ cannot use `+=` in a let chain @@ -56,6 +62,12 @@ LL - if let _ = 1 && y += 2 {}; LL + if let _ = 1 && y == 2 {}; | -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/let-chains-assign-add-incorrect.rs:24:8 + | +LL | if let _ = 1 && y += 2 {}; + | ^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0308`.