Skip to content

Commit c83602a

Browse files
committed
When type-checking binops, LHS of assign-op like += is invariant.
Therefore we cannot coerce it to a supertype the same way that we can the LHS of `+`. Addresses issue 52126.
1 parent 4260c8b commit c83602a

File tree

1 file changed

+18
-11
lines changed
  • src/librustc_typeck/check

1 file changed

+18
-11
lines changed

src/librustc_typeck/check/op.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
165165
op,
166166
is_assign);
167167

168-
let lhs_needs = match is_assign {
169-
IsAssign::Yes => Needs::MutPlace,
170-
IsAssign::No => Needs::None
168+
let lhs_ty = match is_assign {
169+
IsAssign::No => {
170+
// Find a suitable supertype of the LHS expression's type, by coercing to
171+
// a type variable, to pass as the `Self` to the trait, avoiding invariant
172+
// trait matching creating lifetime constraints that are too strict.
173+
// E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
174+
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
175+
let lhs_ty = self.check_expr_with_needs(lhs_expr, Needs::None);
176+
let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span));
177+
self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No)
178+
}
179+
IsAssign::Yes => {
180+
// rust-lang/rust#52126: We have to use strict
181+
// equivalence on the LHS of an assign-op like `+=`;
182+
// overwritten or mutably-borrowed places cannot be
183+
// coerced to a supertype.
184+
self.check_expr_with_needs(lhs_expr, Needs::MutPlace)
185+
}
171186
};
172-
// Find a suitable supertype of the LHS expression's type, by coercing to
173-
// a type variable, to pass as the `Self` to the trait, avoiding invariant
174-
// trait matching creating lifetime constraints that are too strict.
175-
// E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
176-
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
177-
let lhs_ty = self.check_expr_with_needs(lhs_expr, lhs_needs);
178-
let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span));
179-
let lhs_ty = self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No);
180187
let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
181188

182189
// NB: As we have not yet type-checked the RHS, we don't have the

0 commit comments

Comments
 (0)