]> git.lizzy.rs Git - rust.git/commitdiff
When type-checking binops, LHS of assign-op like `+=` is invariant.
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Thu, 19 Jul 2018 13:10:14 +0000 (15:10 +0200)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Fri, 20 Jul 2018 11:12:30 +0000 (13:12 +0200)
Therefore we cannot coerce it to a supertype the same way that we can
the LHS of `+`.

Addresses issue 52126.

src/librustc_typeck/check/op.rs

index 46746d4bd298aad5ee0e050400f811e87b4880e1..fb153464dff112ade1d4b61dda09057abeeaa949 100644 (file)
@@ -165,18 +165,25 @@ fn check_overloaded_binop(&self,
                op,
                is_assign);
 
-        let lhs_needs = match is_assign {
-            IsAssign::Yes => Needs::MutPlace,
-            IsAssign::No => Needs::None
+        let lhs_ty = match is_assign {
+            IsAssign::No => {
+                // Find a suitable supertype of the LHS expression's type, by coercing to
+                // a type variable, to pass as the `Self` to the trait, avoiding invariant
+                // trait matching creating lifetime constraints that are too strict.
+                // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
+                // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
+                let lhs_ty = self.check_expr_with_needs(lhs_expr, Needs::None);
+                let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span));
+                self.demand_coerce(lhs_expr, lhs_ty, fresh_var,  AllowTwoPhase::No)
+            }
+            IsAssign::Yes => {
+                // rust-lang/rust#52126: We have to use strict
+                // equivalence on the LHS of an assign-op like `+=`;
+                // overwritten or mutably-borrowed places cannot be
+                // coerced to a supertype.
+                self.check_expr_with_needs(lhs_expr, Needs::MutPlace)
+            }
         };
-        // Find a suitable supertype of the LHS expression's type, by coercing to
-        // a type variable, to pass as the `Self` to the trait, avoiding invariant
-        // trait matching creating lifetime constraints that are too strict.
-        // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
-        // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
-        let lhs_ty = self.check_expr_with_needs(lhs_expr, lhs_needs);
-        let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span));
-        let lhs_ty = self.demand_coerce(lhs_expr, lhs_ty, fresh_var,  AllowTwoPhase::No);
         let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
 
         // NB: As we have not yet type-checked the RHS, we don't have the