@@ -2815,11 +2815,19 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
28152815 BinopAssignment => PreferMutLvalue ,
28162816 SimpleBinop => NoPreference
28172817 } ;
2818- check_expr_with_lvalue_pref ( fcx, & * lhs, lvalue_pref) ;
2818+ check_expr_with_lvalue_pref ( fcx, lhs, lvalue_pref) ;
28192819
28202820 // 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+ } ) ;
28232831
28242832 if ty:: type_is_integral ( lhs_t) && ast_util:: is_shift_binop ( op. node ) {
28252833 // 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>,
50715079 }
50725080}
50735081
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 >
50805087{
50815088 let mut ty = fcx. resolve_type_vars_if_possible ( ty) ;
50825089
5083- // If not, error.
50845090 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+ }
50915104 }
50925105
50935106 ty
50945107}
50955108
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+
50965121// Returns true if b contains a break that can exit from b
50975122pub fn may_break ( cx : & ty:: ctxt , id : ast:: NodeId , b : & ast:: Block ) -> bool {
50985123 // First: is there an unlabeled break immediately
0 commit comments