1212
1313use super :: FnCtxt ;
1414use super :: method:: MethodCallee ;
15- use rustc:: ty:: { self , Ty , TypeFoldable , PreferMutLvalue , TypeVariants } ;
15+ use rustc:: ty:: { self , Ty , TypeFoldable , NoPreference , PreferMutLvalue , TypeVariants } ;
1616use rustc:: ty:: TypeVariants :: { TyStr , TyRef } ;
1717use rustc:: ty:: adjustment:: { Adjustment , Adjust , AutoBorrow } ;
1818use rustc:: infer:: type_variable:: TypeVariableOrigin ;
@@ -29,12 +29,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2929 lhs_expr : & ' gcx hir:: Expr ,
3030 rhs_expr : & ' gcx hir:: Expr ) -> Ty < ' tcx >
3131 {
32- let lhs_ty = self . check_expr_with_lvalue_pref ( lhs_expr, PreferMutLvalue ) ;
33-
34- let lhs_ty = self . resolve_type_vars_with_obligations ( lhs_ty) ;
35- let ( rhs_ty, return_ty) =
36- self . check_overloaded_binop ( expr, lhs_expr, lhs_ty, rhs_expr, op, IsAssign :: Yes ) ;
37- let rhs_ty = self . resolve_type_vars_with_obligations ( rhs_ty) ;
32+ let ( lhs_ty, rhs_ty, return_ty) =
33+ self . check_overloaded_binop ( expr, lhs_expr, rhs_expr, op, IsAssign :: Yes ) ;
3834
3935 let ty = if !lhs_ty. is_ty_var ( ) && !rhs_ty. is_ty_var ( )
4036 && is_builtin_binop ( lhs_ty, rhs_ty, op) {
@@ -73,27 +69,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7369 lhs_expr,
7470 rhs_expr) ;
7571
76- let lhs_ty = self . check_expr ( lhs_expr) ;
77- let lhs_ty = self . resolve_type_vars_with_obligations ( lhs_ty) ;
78-
7972 match BinOpCategory :: from ( op) {
8073 BinOpCategory :: Shortcircuit => {
8174 // && and || are a simple case.
75+ self . check_expr_coercable_to_type ( lhs_expr, tcx. types . bool ) ;
8276 let lhs_diverges = self . diverges . get ( ) ;
83- self . demand_suptype ( lhs_expr. span , tcx. mk_bool ( ) , lhs_ty) ;
84- self . check_expr_coercable_to_type ( rhs_expr, tcx. mk_bool ( ) ) ;
77+ self . check_expr_coercable_to_type ( rhs_expr, tcx. types . bool ) ;
8578
8679 // Depending on the LHS' value, the RHS can never execute.
8780 self . diverges . set ( lhs_diverges) ;
8881
89- tcx. mk_bool ( )
82+ tcx. types . bool
9083 }
9184 _ => {
9285 // Otherwise, we always treat operators as if they are
9386 // overloaded. This is the way to be most flexible w/r/t
9487 // types that get inferred.
95- let ( rhs_ty, return_ty) =
96- self . check_overloaded_binop ( expr, lhs_expr, lhs_ty ,
88+ let ( lhs_ty , rhs_ty, return_ty) =
89+ self . check_overloaded_binop ( expr, lhs_expr,
9790 rhs_expr, op, IsAssign :: No ) ;
9891
9992 // Supply type inference hints if relevant. Probably these
@@ -108,7 +101,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
108101 // deduce that the result type should be `u32`, even
109102 // though we don't know yet what type 2 has and hence
110103 // can't pin this down to a specific impl.
111- let rhs_ty = self . resolve_type_vars_with_obligations ( rhs_ty) ;
112104 if
113105 !lhs_ty. is_ty_var ( ) && !rhs_ty. is_ty_var ( ) &&
114106 is_builtin_binop ( lhs_ty, rhs_ty, op)
@@ -164,17 +156,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
164156 fn check_overloaded_binop ( & self ,
165157 expr : & ' gcx hir:: Expr ,
166158 lhs_expr : & ' gcx hir:: Expr ,
167- lhs_ty : Ty < ' tcx > ,
168159 rhs_expr : & ' gcx hir:: Expr ,
169160 op : hir:: BinOp ,
170161 is_assign : IsAssign )
171- -> ( Ty < ' tcx > , Ty < ' tcx > )
162+ -> ( Ty < ' tcx > , Ty < ' tcx > , Ty < ' tcx > )
172163 {
173- debug ! ( "check_overloaded_binop(expr.id={}, lhs_ty ={:?}, is_assign={:?})" ,
164+ debug ! ( "check_overloaded_binop(expr.id={}, op ={:?}, is_assign={:?})" ,
174165 expr. id,
175- lhs_ty ,
166+ op ,
176167 is_assign) ;
177168
169+ let lhs_pref = match is_assign {
170+ IsAssign :: Yes => PreferMutLvalue ,
171+ IsAssign :: No => NoPreference
172+ } ;
173+ // Find a suitable supertype of the LHS expression's type, by coercing to
174+ // a type variable, to pass as the `Self` to the trait, avoiding invariant
175+ // trait matching creating lifetime constraints that are too strict.
176+ // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
177+ // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
178+ let lhs_ty = self . check_expr_coercable_to_type_with_lvalue_pref ( lhs_expr,
179+ self . next_ty_var ( TypeVariableOrigin :: MiscVariable ( lhs_expr. span ) ) ,
180+ lhs_pref) ;
181+ let lhs_ty = self . resolve_type_vars_with_obligations ( lhs_ty) ;
182+
178183 // NB: As we have not yet type-checked the RHS, we don't have the
179184 // type at hand. Make a variable to represent it. The whole reason
180185 // for this indirection is so that, below, we can check the expr
@@ -187,6 +192,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
187192
188193 // see `NB` above
189194 let rhs_ty = self . check_expr_coercable_to_type ( rhs_expr, rhs_ty_var) ;
195+ let rhs_ty = self . resolve_type_vars_with_obligations ( rhs_ty) ;
190196
191197 let return_ty = match result {
192198 Ok ( method) => {
@@ -296,7 +302,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
296302 }
297303 } ;
298304
299- ( rhs_ty_var , return_ty)
305+ ( lhs_ty , rhs_ty , return_ty)
300306 }
301307
302308 fn check_str_addition ( & self ,
0 commit comments