@@ -25,7 +25,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2525
2626        let  ty =
2727            if  !lhs_ty. is_ty_var ( )  && !rhs_ty. is_ty_var ( )  && is_builtin_binop ( lhs_ty,  rhs_ty,  op)  { 
28-                 self . enforce_builtin_binop_types ( lhs,  lhs_ty,  rhs,  rhs_ty,  op) ; 
28+                 self . enforce_builtin_binop_types ( & lhs. span ,  lhs_ty,  & rhs. span ,  rhs_ty,  op) ; 
2929                self . tcx . mk_unit ( ) 
3030            }  else  { 
3131                return_ty
@@ -86,8 +86,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8686                    && !rhs_ty. is_ty_var ( ) 
8787                    && is_builtin_binop ( lhs_ty,  rhs_ty,  op) 
8888                { 
89-                     let  builtin_return_ty =
90-                         self . enforce_builtin_binop_types ( lhs_expr,  lhs_ty,  rhs_expr,  rhs_ty,  op) ; 
89+                     let  builtin_return_ty = self . enforce_builtin_binop_types ( 
90+                         & lhs_expr. span , 
91+                         lhs_ty, 
92+                         & rhs_expr. span , 
93+                         rhs_ty, 
94+                         op, 
95+                     ) ; 
9196                    self . demand_suptype ( expr. span ,  builtin_return_ty,  return_ty) ; 
9297                } 
9398
@@ -98,19 +103,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
98103
99104    fn  enforce_builtin_binop_types ( 
100105        & self , 
101-         lhs_expr :  & ' tcx  hir :: Expr < ' tcx > , 
106+         lhs_span :  & Span , 
102107        lhs_ty :  Ty < ' tcx > , 
103-         rhs_expr :  & ' tcx  hir :: Expr < ' tcx > , 
108+         rhs_span :  & Span , 
104109        rhs_ty :  Ty < ' tcx > , 
105110        op :  hir:: BinOp , 
106111    )  -> Ty < ' tcx >  { 
107112        debug_assert ! ( is_builtin_binop( lhs_ty,  rhs_ty,  op) ) ; 
108113
114+         // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. 
115+         // (See https://github.com/rust-lang/rust/issues/57447.) 
116+         let  ( lhs_ty,  rhs_ty)  = ( deref_ty_if_possible ( lhs_ty) ,  deref_ty_if_possible ( rhs_ty) ) ; 
117+ 
109118        let  tcx = self . tcx ; 
110119        match  BinOpCategory :: from ( op)  { 
111120            BinOpCategory :: Shortcircuit  => { 
112-                 self . demand_suptype ( lhs_expr . span ,  tcx. mk_bool ( ) ,  lhs_ty) ; 
113-                 self . demand_suptype ( rhs_expr . span ,  tcx. mk_bool ( ) ,  rhs_ty) ; 
121+                 self . demand_suptype ( * lhs_span ,  tcx. mk_bool ( ) ,  lhs_ty) ; 
122+                 self . demand_suptype ( * rhs_span ,  tcx. mk_bool ( ) ,  rhs_ty) ; 
114123                tcx. mk_bool ( ) 
115124            } 
116125
@@ -121,13 +130,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
121130
122131            BinOpCategory :: Math  | BinOpCategory :: Bitwise  => { 
123132                // both LHS and RHS and result will have the same type 
124-                 self . demand_suptype ( rhs_expr . span ,  lhs_ty,  rhs_ty) ; 
133+                 self . demand_suptype ( * rhs_span ,  lhs_ty,  rhs_ty) ; 
125134                lhs_ty
126135            } 
127136
128137            BinOpCategory :: Comparison  => { 
129138                // both LHS and RHS and result will have the same type 
130-                 self . demand_suptype ( rhs_expr . span ,  lhs_ty,  rhs_ty) ; 
139+                 self . demand_suptype ( * rhs_span ,  lhs_ty,  rhs_ty) ; 
131140                tcx. mk_bool ( ) 
132141            } 
133142        } 
@@ -862,6 +871,14 @@ enum Op {
862871    Unary ( hir:: UnOp ,  Span ) , 
863872} 
864873
874+ /// Dereferences a single level of immutable referencing. 
875+ fn  deref_ty_if_possible < ' tcx > ( ty :  Ty < ' tcx > )  -> Ty < ' tcx >  { 
876+     match  ty. kind  { 
877+         ty:: Ref ( _,  ty,  hir:: Mutability :: Not )  => ty, 
878+         _ => ty, 
879+     } 
880+ } 
881+ 
865882/// Returns `true` if this is a built-in arithmetic operation (e.g., u32 
866883/// + u32, i16x4 == i16x4) and false if these types would have to be 
867884/// overloaded to be legal. There are two reasons that we distinguish 
@@ -878,7 +895,11 @@ enum Op {
878895/// Reason #2 is the killer. I tried for a while to always use 
879896/// overloaded logic and just check the types in constants/codegen after 
880897/// the fact, and it worked fine, except for SIMD types. -nmatsakis 
881- fn  is_builtin_binop ( lhs :  Ty < ' _ > ,  rhs :  Ty < ' _ > ,  op :  hir:: BinOp )  -> bool  { 
898+ fn  is_builtin_binop < ' tcx > ( lhs :  Ty < ' tcx > ,  rhs :  Ty < ' tcx > ,  op :  hir:: BinOp )  -> bool  { 
899+     // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. 
900+     // (See https://github.com/rust-lang/rust/issues/57447.) 
901+     let  ( lhs,  rhs)  = ( deref_ty_if_possible ( lhs) ,  deref_ty_if_possible ( rhs) ) ; 
902+ 
882903    match  BinOpCategory :: from ( op)  { 
883904        BinOpCategory :: Shortcircuit  => true , 
884905
0 commit comments