@@ -2815,11 +2815,19 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2815
2815
BinopAssignment => PreferMutLvalue ,
2816
2816
SimpleBinop => NoPreference
2817
2817
} ;
2818
- check_expr_with_lvalue_pref ( fcx, & * lhs, lvalue_pref) ;
2818
+ check_expr_with_lvalue_pref ( fcx, lhs, lvalue_pref) ;
2819
2819
2820
2820
// Callee does bot / err checking
2821
- let lhs_t = structurally_resolved_type ( fcx, lhs. span ,
2822
- fcx. expr_ty ( & * lhs) ) ;
2821
+ let lhs_t =
2822
+ structurally_resolve_type_or_else ( fcx, lhs. span , fcx. expr_ty ( lhs) , || {
2823
+ if ast_util:: is_symmetric_binop ( op. node ) {
2824
+ // Try RHS first
2825
+ check_expr ( fcx, & * * rhs) ;
2826
+ fcx. expr_ty ( & * * rhs)
2827
+ } else {
2828
+ fcx. tcx ( ) . types . err
2829
+ }
2830
+ } ) ;
2823
2831
2824
2832
if ty:: type_is_integral ( lhs_t) && ast_util:: is_shift_binop ( op. node ) {
2825
2833
// Shift is a special case: rhs must be uint, no matter what lhs is
@@ -5071,28 +5079,45 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5071
5079
}
5072
5080
}
5073
5081
5074
- // Resolves `typ` by a single level if `typ` is a type variable. If no
5075
- // resolution is possible, then an error is reported.
5076
- pub fn structurally_resolved_type < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
5077
- sp : Span ,
5078
- ty : Ty < ' tcx > )
5079
- -> Ty < ' tcx >
5082
+ fn structurally_resolve_type_or_else < ' a , ' tcx , F > ( fcx : & FnCtxt < ' a , ' tcx > ,
5083
+ sp : Span ,
5084
+ ty : Ty < ' tcx > ,
5085
+ f : F ) -> Ty < ' tcx >
5086
+ where F : Fn ( ) -> Ty < ' tcx >
5080
5087
{
5081
5088
let mut ty = fcx. resolve_type_vars_if_possible ( ty) ;
5082
5089
5083
- // If not, error.
5084
5090
if ty:: type_is_ty_var ( ty) {
5085
- fcx. type_error_message ( sp, |_actual| {
5086
- "the type of this value must be known in this \
5087
- context". to_string ( )
5088
- } , ty, None ) ;
5089
- demand:: suptype ( fcx, sp, fcx. tcx ( ) . types . err , ty) ;
5090
- ty = fcx. tcx ( ) . types . err ;
5091
+ let alternative = f ( ) ;
5092
+
5093
+ // If not, error.
5094
+ if ty:: type_is_ty_var ( alternative) || ty:: type_is_error ( alternative) {
5095
+ fcx. type_error_message ( sp, |_actual| {
5096
+ "the type of this value must be known in this context" . to_string ( )
5097
+ } , ty, None ) ;
5098
+ demand:: suptype ( fcx, sp, fcx. tcx ( ) . types . err , ty) ;
5099
+ ty = fcx. tcx ( ) . types . err ;
5100
+ } else {
5101
+ demand:: suptype ( fcx, sp, alternative, ty) ;
5102
+ ty = alternative;
5103
+ }
5091
5104
}
5092
5105
5093
5106
ty
5094
5107
}
5095
5108
5109
+ // Resolves `typ` by a single level if `typ` is a type variable. If no
5110
+ // resolution is possible, then an error is reported.
5111
+ pub fn structurally_resolved_type < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
5112
+ sp : Span ,
5113
+ ty : Ty < ' tcx > )
5114
+ -> Ty < ' tcx >
5115
+ {
5116
+ structurally_resolve_type_or_else ( fcx, sp, ty, || {
5117
+ fcx. tcx ( ) . types . err
5118
+ } )
5119
+ }
5120
+
5096
5121
// Returns true if b contains a break that can exit from b
5097
5122
pub fn may_break ( cx : & ty:: ctxt , id : ast:: NodeId , b : & ast:: Block ) -> bool {
5098
5123
// First: is there an unlabeled break immediately
0 commit comments