@@ -621,18 +621,19 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
621
621
match ( eval_const_expr_partial ( tcx, & a, ty_hint, fn_args) ?,
622
622
eval_const_expr_partial ( tcx, & b, b_ty, fn_args) ?) {
623
623
( Float ( a) , Float ( b) ) => {
624
+ use std:: cmp:: Ordering :: * ;
624
625
match op. node {
625
- hir:: BiAdd => Float ( a + b) ,
626
- hir:: BiSub => Float ( a - b) ,
627
- hir:: BiMul => Float ( a * b) ,
628
- hir:: BiDiv => Float ( a / b) ,
629
- hir:: BiRem => Float ( a % b) ,
630
- hir:: BiEq => Bool ( a == b ) ,
631
- hir:: BiLt => Bool ( a < b ) ,
632
- hir:: BiLe => Bool ( a <= b ) ,
633
- hir:: BiNe => Bool ( a != b ) ,
634
- hir:: BiGe => Bool ( a >= b ) ,
635
- hir:: BiGt => Bool ( a > b ) ,
626
+ hir:: BiAdd => Float ( math ! ( e , a + b) ) ,
627
+ hir:: BiSub => Float ( math ! ( e , a - b) ) ,
628
+ hir:: BiMul => Float ( math ! ( e , a * b) ) ,
629
+ hir:: BiDiv => Float ( math ! ( e , a / b) ) ,
630
+ hir:: BiRem => Float ( math ! ( e , a % b) ) ,
631
+ hir:: BiEq => Bool ( math ! ( e , a . try_cmp ( b ) ) == Equal ) ,
632
+ hir:: BiLt => Bool ( math ! ( e , a . try_cmp ( b ) ) == Less ) ,
633
+ hir:: BiLe => Bool ( math ! ( e , a . try_cmp ( b ) ) != Greater ) ,
634
+ hir:: BiNe => Bool ( math ! ( e , a . try_cmp ( b ) ) != Equal ) ,
635
+ hir:: BiGe => Bool ( math ! ( e , a . try_cmp ( b ) ) != Less ) ,
636
+ hir:: BiGt => Bool ( math ! ( e , a . try_cmp ( b ) ) == Greater ) ,
636
637
_ => signal ! ( e, InvalidOpForFloats ( op. node) ) ,
637
638
}
638
639
}
@@ -1078,13 +1079,13 @@ fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::
1078
1079
}
1079
1080
} ,
1080
1081
ty:: TyFloat ( ast:: FloatTy :: F64 ) => match val. erase_type ( ) {
1081
- Infer ( u) => Ok ( Float ( u as f64 ) ) ,
1082
- InferSigned ( i) => Ok ( Float ( i as f64 ) ) ,
1082
+ Infer ( u) => Ok ( Float ( F64 ( u as f64 ) ) ) ,
1083
+ InferSigned ( i) => Ok ( Float ( F64 ( i as f64 ) ) ) ,
1083
1084
_ => bug ! ( "ConstInt::erase_type returned something other than Infer/InferSigned" ) ,
1084
1085
} ,
1085
1086
ty:: TyFloat ( ast:: FloatTy :: F32 ) => match val. erase_type ( ) {
1086
- Infer ( u) => Ok ( Float ( u as f32 as f64 ) ) ,
1087
- InferSigned ( i) => Ok ( Float ( i as f32 as f64 ) ) ,
1087
+ Infer ( u) => Ok ( Float ( F32 ( u as f32 ) ) ) ,
1088
+ InferSigned ( i) => Ok ( Float ( F32 ( i as f32 ) ) ) ,
1088
1089
_ => bug ! ( "ConstInt::erase_type returned something other than Infer/InferSigned" ) ,
1089
1090
} ,
1090
1091
ty:: TyRawPtr ( _) => Err ( ErrKind :: UnimplementedConstVal ( "casting an address to a raw ptr" ) ) ,
@@ -1097,13 +1098,35 @@ fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::
1097
1098
}
1098
1099
}
1099
1100
1100
- fn cast_const_float < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , f : f64 , ty : ty:: Ty ) -> CastResult {
1101
+ fn cast_const_float < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1102
+ val : ConstFloat ,
1103
+ ty : ty:: Ty ) -> CastResult {
1101
1104
match ty. sty {
1102
- ty:: TyInt ( _) if f >= 0.0 => cast_const_int ( tcx, Infer ( f as u64 ) , ty) ,
1103
- ty:: TyInt ( _) => cast_const_int ( tcx, InferSigned ( f as i64 ) , ty) ,
1104
- ty:: TyUint ( _) if f >= 0.0 => cast_const_int ( tcx, Infer ( f as u64 ) , ty) ,
1105
- ty:: TyFloat ( ast:: FloatTy :: F64 ) => Ok ( Float ( f) ) ,
1106
- ty:: TyFloat ( ast:: FloatTy :: F32 ) => Ok ( Float ( f as f32 as f64 ) ) ,
1105
+ ty:: TyInt ( _) | ty:: TyUint ( _) => {
1106
+ let i = match val {
1107
+ F32 ( f) if f >= 0.0 => Infer ( f as u64 ) ,
1108
+ FInfer { f64 : f, .. } |
1109
+ F64 ( f) if f >= 0.0 => Infer ( f as u64 ) ,
1110
+
1111
+ F32 ( f) => InferSigned ( f as i64 ) ,
1112
+ FInfer { f64 : f, .. } |
1113
+ F64 ( f) => InferSigned ( f as i64 )
1114
+ } ;
1115
+
1116
+ if let ( InferSigned ( _) , & ty:: TyUint ( _) ) = ( i, & ty. sty ) {
1117
+ return Err ( CannotCast ) ;
1118
+ }
1119
+
1120
+ cast_const_int ( tcx, i, ty)
1121
+ }
1122
+ ty:: TyFloat ( ast:: FloatTy :: F64 ) => Ok ( Float ( F64 ( match val {
1123
+ F32 ( f) => f as f64 ,
1124
+ FInfer { f64 : f, .. } | F64 ( f) => f
1125
+ } ) ) ) ,
1126
+ ty:: TyFloat ( ast:: FloatTy :: F32 ) => Ok ( Float ( F32 ( match val {
1127
+ F64 ( f) => f as f32 ,
1128
+ FInfer { f32 : f, .. } | F32 ( f) => f
1129
+ } ) ) ) ,
1107
1130
_ => Err ( CannotCast ) ,
1108
1131
}
1109
1132
}
@@ -1161,33 +1184,43 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
1161
1184
infer ( Infer ( n) , tcx, & ty:: TyUint ( ity) ) . map ( Integral )
1162
1185
} ,
1163
1186
1164
- LitKind :: Float ( ref n, _) |
1187
+ LitKind :: Float ( ref n, fty) => {
1188
+ Ok ( Float ( parse_float ( n, Some ( fty) , span) ) )
1189
+ }
1165
1190
LitKind :: FloatUnsuffixed ( ref n) => {
1166
- if let Ok ( x) = n. parse :: < f64 > ( ) {
1167
- Ok ( Float ( x) )
1168
- } else {
1169
- // FIXME(#31407) this is only necessary because float parsing is buggy
1170
- span_bug ! ( span, "could not evaluate float literal (see issue #31407)" ) ;
1171
- }
1191
+ let fty_hint = match ty_hint. map ( |t| & t. sty ) {
1192
+ Some ( & ty:: TyFloat ( fty) ) => Some ( fty) ,
1193
+ _ => None
1194
+ } ;
1195
+ Ok ( Float ( parse_float ( n, fty_hint, span) ) )
1172
1196
}
1173
1197
LitKind :: Bool ( b) => Ok ( Bool ( b) ) ,
1174
1198
LitKind :: Char ( c) => Ok ( Char ( c) ) ,
1175
1199
}
1176
1200
}
1177
1201
1202
+ fn parse_float ( num : & str , fty_hint : Option < ast:: FloatTy > , span : Span ) -> ConstFloat {
1203
+ let val = match fty_hint {
1204
+ Some ( ast:: FloatTy :: F32 ) => num. parse :: < f32 > ( ) . map ( F32 ) ,
1205
+ Some ( ast:: FloatTy :: F64 ) => num. parse :: < f64 > ( ) . map ( F64 ) ,
1206
+ None => {
1207
+ num. parse :: < f32 > ( ) . and_then ( |f32| {
1208
+ num. parse :: < f64 > ( ) . map ( |f64| {
1209
+ FInfer { f32 : f32, f64 : f64 }
1210
+ } )
1211
+ } )
1212
+ }
1213
+ } ;
1214
+ val. unwrap_or_else ( |_| {
1215
+ // FIXME(#31407) this is only necessary because float parsing is buggy
1216
+ span_bug ! ( span, "could not evaluate float literal (see issue #31407)" ) ;
1217
+ } )
1218
+ }
1219
+
1178
1220
pub fn compare_const_vals ( a : & ConstVal , b : & ConstVal ) -> Option < Ordering > {
1179
1221
match ( a, b) {
1180
1222
( & Integral ( a) , & Integral ( b) ) => a. try_cmp ( b) . ok ( ) ,
1181
- ( & Float ( a) , & Float ( b) ) => {
1182
- // This is pretty bad but it is the existing behavior.
1183
- Some ( if a == b {
1184
- Ordering :: Equal
1185
- } else if a < b {
1186
- Ordering :: Less
1187
- } else {
1188
- Ordering :: Greater
1189
- } )
1190
- }
1223
+ ( & Float ( a) , & Float ( b) ) => a. try_cmp ( b) . ok ( ) ,
1191
1224
( & Str ( ref a) , & Str ( ref b) ) => Some ( a. cmp ( b) ) ,
1192
1225
( & Bool ( a) , & Bool ( b) ) => Some ( a. cmp ( & b) ) ,
1193
1226
( & ByteStr ( ref a) , & ByteStr ( ref b) ) => Some ( a. cmp ( b) ) ,
0 commit comments