@@ -621,18 +621,19 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
621621 match ( eval_const_expr_partial ( tcx, & a, ty_hint, fn_args) ?,
622622 eval_const_expr_partial ( tcx, & b, b_ty, fn_args) ?) {
623623 ( Float ( a) , Float ( b) ) => {
624+ use std:: cmp:: Ordering :: * ;
624625 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 ) ,
636637 _ => signal ! ( e, InvalidOpForFloats ( op. node) ) ,
637638 }
638639 }
@@ -1078,13 +1079,13 @@ fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::
10781079 }
10791080 } ,
10801081 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 ) ) ) ,
10831084 _ => bug ! ( "ConstInt::erase_type returned something other than Infer/InferSigned" ) ,
10841085 } ,
10851086 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 ) ) ) ,
10881089 _ => bug ! ( "ConstInt::erase_type returned something other than Infer/InferSigned" ) ,
10891090 } ,
10901091 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::
10971098 }
10981099}
10991100
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 {
11011104 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+ } ) ) ) ,
11071130 _ => Err ( CannotCast ) ,
11081131 }
11091132}
@@ -1161,33 +1184,43 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
11611184 infer ( Infer ( n) , tcx, & ty:: TyUint ( ity) ) . map ( Integral )
11621185 } ,
11631186
1164- LitKind :: Float ( ref n, _) |
1187+ LitKind :: Float ( ref n, fty) => {
1188+ Ok ( Float ( parse_float ( n, Some ( fty) , span) ) )
1189+ }
11651190 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) ) )
11721196 }
11731197 LitKind :: Bool ( b) => Ok ( Bool ( b) ) ,
11741198 LitKind :: Char ( c) => Ok ( Char ( c) ) ,
11751199 }
11761200}
11771201
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+
11781220pub fn compare_const_vals ( a : & ConstVal , b : & ConstVal ) -> Option < Ordering > {
11791221 match ( a, b) {
11801222 ( & 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 ( ) ,
11911224 ( & Str ( ref a) , & Str ( ref b) ) => Some ( a. cmp ( b) ) ,
11921225 ( & Bool ( a) , & Bool ( b) ) => Some ( a. cmp ( & b) ) ,
11931226 ( & ByteStr ( ref a) , & ByteStr ( ref b) ) => Some ( a. cmp ( b) ) ,
0 commit comments