Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 11 additions & 21 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -86,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
});

ty
self.tcx.types.unit
}

/// Checks a potentially overloaded binary operator.
Expand Down Expand Up @@ -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.)
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/parser/let-chains-assign-add-incorrect.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/parser/let-chains-assign-add-incorrect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down
20 changes: 16 additions & 4 deletions tests/ui/parser/let-chains-assign-add-incorrect.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
| ^^^^^^^^^
Expand Down Expand Up @@ -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
Expand All @@ -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`.
Loading