]> git.lizzy.rs Git - rust.git/commitdiff
don't be a breaking change, even in presence of overflowing literals
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Wed, 9 Mar 2016 18:27:36 +0000 (19:27 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 10 Mar 2016 11:50:13 +0000 (12:50 +0100)
src/librustc/middle/const_eval.rs
src/librustc_const_eval/int.rs
src/test/compile-fail/enum-discrim-too-small2.rs
src/test/compile-fail/lint-type-limits2.rs
src/test/compile-fail/lint-type-limits3.rs
src/test/run-pass/const-negation.rs

index 3690f0c1d664b95138bef58fc1388e35dced8b6f..d97df585edc053e9c3a56fd859ab3b96108b6066 100644 (file)
@@ -855,10 +855,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
           debug!("const call({:?})", call_args);
           try!(eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args)))
       },
-      hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety, lit.span) {
-          Ok(val) => val,
-          Err(err) => signal!(e, Math(err)),
-      },
+      hir::ExprLit(ref lit) => try!(lit_to_const(&lit.node, tcx, ety, lit.span)),
       hir::ExprBlock(ref block) => {
         match block.expr {
             Some(ref expr) => try!(eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)),
@@ -926,7 +923,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
         if let Tuple(tup_id) = c {
             if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node {
                 if index.node < fields.len() {
-                    return eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args)
+                    try!(eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args))
                 } else {
                     signal!(e, TupleIndexOutOfBounds);
                 }
@@ -947,7 +944,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                 // if the idents are compared run-pass/issue-19244 fails
                 if let Some(f) = fields.iter().find(|f| f.name.node
                                                      == field_name.node) {
-                    return eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args)
+                    try!(eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args))
                 } else {
                     signal!(e, MissingStructField);
                 }
@@ -974,22 +971,6 @@ fn infer<'tcx>(
     span: Span
 ) -> Result<ConstInt, ConstEvalErr> {
     use syntax::ast::*;
-    const I8MAX: u64 = ::std::i8::MAX as u64;
-    const I16MAX: u64 = ::std::i16::MAX as u64;
-    const I32MAX: u64 = ::std::i32::MAX as u64;
-    const I64MAX: u64 = ::std::i64::MAX as u64;
-
-    const U8MAX: u64 = ::std::u8::MAX as u64;
-    const U16MAX: u64 = ::std::u16::MAX as u64;
-    const U32MAX: u64 = ::std::u32::MAX as u64;
-
-    const I8MAXI: i64 = ::std::i8::MAX as i64;
-    const I16MAXI: i64 = ::std::i16::MAX as i64;
-    const I32MAXI: i64 = ::std::i32::MAX as i64;
-
-    const I8MINI: i64 = ::std::i8::MIN as i64;
-    const I16MINI: i64 = ::std::i16::MIN as i64;
-    const I32MINI: i64 = ::std::i32::MIN as i64;
 
     let err = |e| ConstEvalErr {
         span: span,
@@ -1009,41 +990,38 @@ fn infer<'tcx>(
         (&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result),
         (&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result),
 
-        (&ty::TyInt(IntTy::I8), Infer(i @ 0...I8MAX)) => Ok(I8(i as i8)),
-        (&ty::TyInt(IntTy::I16), Infer(i @ 0...I16MAX)) => Ok(I16(i as i16)),
-        (&ty::TyInt(IntTy::I32), Infer(i @ 0...I32MAX)) => Ok(I32(i as i32)),
-        (&ty::TyInt(IntTy::I64), Infer(i @ 0...I64MAX)) => Ok(I64(i as i64)),
-        (&ty::TyInt(IntTy::Is), Infer(i @ 0...I64MAX)) => {
+        (&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i64 as i8)),
+        (&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i64 as i16)),
+        (&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i64 as i32)),
+        (&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i64)),
+        (&ty::TyInt(IntTy::Is), Infer(i)) => {
             match ConstIsize::new(i as i64, tcx.sess.target.int_type) {
                 Ok(val) => Ok(Isize(val)),
-                Err(e) => Err(err(e.into())),
+                Err(_) => Ok(Isize(ConstIsize::Is32(i as i64 as i32))),
             }
         },
-        (&ty::TyInt(_), Infer(_)) => Err(err(Math(ConstMathErr::NotInRange))),
 
-        (&ty::TyInt(IntTy::I8), InferSigned(i @ I8MINI...I8MAXI)) => Ok(I8(i as i8)),
-        (&ty::TyInt(IntTy::I16), InferSigned(i @ I16MINI...I16MAXI)) => Ok(I16(i as i16)),
-        (&ty::TyInt(IntTy::I32), InferSigned(i @ I32MINI...I32MAXI)) => Ok(I32(i as i32)),
+        (&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)),
+        (&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)),
+        (&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)),
         (&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i)),
         (&ty::TyInt(IntTy::Is), InferSigned(i)) => {
             match ConstIsize::new(i, tcx.sess.target.int_type) {
                 Ok(val) => Ok(Isize(val)),
-                Err(e) => Err(err(e.into())),
+                Err(_) => Ok(Isize(ConstIsize::Is32(i as i32))),
             }
         },
-        (&ty::TyInt(_), InferSigned(_)) => Err(err(Math(ConstMathErr::NotInRange))),
 
-        (&ty::TyUint(UintTy::U8), Infer(i @ 0...U8MAX)) => Ok(U8(i as u8)),
-        (&ty::TyUint(UintTy::U16), Infer(i @ 0...U16MAX)) => Ok(U16(i as u16)),
-        (&ty::TyUint(UintTy::U32), Infer(i @ 0...U32MAX)) => Ok(U32(i as u32)),
+        (&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)),
+        (&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)),
+        (&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)),
         (&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i)),
         (&ty::TyUint(UintTy::Us), Infer(i)) => {
             match ConstUsize::new(i, tcx.sess.target.uint_type) {
                 Ok(val) => Ok(Usize(val)),
-                Err(e) => Err(err(e.into())),
+                Err(_) => Ok(Usize(ConstUsize::Us32(i as u32))),
             }
         },
-        (&ty::TyUint(_), Infer(_)) => Err(err(Math(ConstMathErr::NotInRange))),
         (&ty::TyUint(_), InferSigned(_)) => Err(err(IntermediateUnsignedNegative)),
 
         (&ty::TyInt(ity), i) => Err(err(TypeMismatch(ity.to_string(), i))),
@@ -1115,19 +1093,25 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
     match ty.sty {
         ty::TyBool if v == 0 => Ok(Bool(false)),
         ty::TyBool if v == 1 => Ok(Bool(true)),
-        ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i8))),
-        ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i16))),
-        ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i32))),
+        ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i64 as i8))),
+        ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i64 as i16))),
+        ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i64 as i32))),
         ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i64))),
         ty::TyInt(ast::IntTy::Is) => {
-            Ok(Integral(Isize(try!(ConstIsize::new(v as i64, tcx.sess.target.int_type)))))
+            match ConstIsize::new(v as i64, tcx.sess.target.int_type) {
+                Ok(val) => Ok(Integral(Isize(val))),
+                Err(_) => Ok(Integral(Isize(ConstIsize::Is32(v as i64 as i32)))),
+            }
         },
         ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
         ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))),
         ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
-        ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
+        ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v))),
         ty::TyUint(ast::UintTy::Us) => {
-            Ok(Integral(Usize(try!(ConstUsize::new(v, tcx.sess.target.uint_type)))))
+            match ConstUsize::new(v, tcx.sess.target.uint_type) {
+                Ok(val) => Ok(Integral(Usize(val))),
+                Err(_) => Ok(Integral(Usize(ConstUsize::Us32(v as u32)))),
+            }
         },
         ty::TyFloat(ast::FloatTy::F64) if val.is_negative() => {
             // FIXME: this could probably be prettier
@@ -1174,57 +1158,37 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
                       tcx: &TyCtxt<'tcx>,
                       ty_hint: Option<Ty<'tcx>>,
                       span: Span,
-                      ) -> Result<ConstVal, ConstMathErr> {
+                      ) -> Result<ConstVal, ConstEvalErr> {
     use syntax::ast::*;
     use syntax::ast::LitIntType::*;
-    const I8MAX: u64 = ::std::i8::MAX as u64;
-    const I16MAX: u64 = ::std::i16::MAX as u64;
-    const I32MAX: u64 = ::std::i32::MAX as u64;
-    const I64MAX: u64 = ::std::i64::MAX as u64;
-    const U8MAX: u64 = ::std::u8::MAX as u64;
-    const U16MAX: u64 = ::std::u16::MAX as u64;
-    const U32MAX: u64 = ::std::u32::MAX as u64;
-    const U64MAX: u64 = ::std::u64::MAX as u64;
     match *lit {
         LitKind::Str(ref s, _) => Ok(Str((*s).clone())),
         LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
         LitKind::Byte(n) => Ok(Integral(U8(n))),
-        LitKind::Int(n @ 0...I8MAX, Signed(IntTy::I8)) => Ok(Integral(I8(n as i8))),
-        LitKind::Int(n @ 0...I16MAX, Signed(IntTy::I16)) => Ok(Integral(I16(n as i16))),
-        LitKind::Int(n @ 0...I32MAX, Signed(IntTy::I32)) => Ok(Integral(I32(n as i32))),
-        LitKind::Int(n @ 0...I64MAX, Signed(IntTy::I64)) => Ok(Integral(I64(n as i64))),
-        LitKind::Int(n, Signed(IntTy::Is)) => {
-            Ok(Integral(Isize(try!(ConstIsize::new(n as i64, tcx.sess.target.int_type)))))
+        LitKind::Int(n, Signed(ity)) => {
+            infer(InferSigned(n as i64), tcx, &ty::TyInt(ity), span).map(Integral)
         },
 
-        LitKind::Int(_, Signed(ty)) => Err(ConstMathErr::LitOutOfRange(ty)),
-
         LitKind::Int(n, Unsuffixed) => {
             match ty_hint.map(|t| &t.sty) {
                 Some(&ty::TyInt(ity)) => {
-                    lit_to_const(&LitKind::Int(n, Signed(ity)), tcx, ty_hint, span)
+                    infer(InferSigned(n as i64), tcx, &ty::TyInt(ity), span).map(Integral)
                 },
                 Some(&ty::TyUint(uty)) => {
-                    lit_to_const(&LitKind::Int(n, Unsigned(uty)), tcx, ty_hint, span)
+                    infer(Infer(n), tcx, &ty::TyUint(uty), span).map(Integral)
                 },
                 None => Ok(Integral(Infer(n))),
                 Some(&ty::TyEnum(ref adt, _)) => {
                     let hints = tcx.lookup_repr_hints(adt.did);
                     let int_ty = tcx.enum_repr_type(hints.iter().next());
-                    lit_to_const(lit, tcx, Some(int_ty.to_ty(tcx)), span)
+                    infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty, span).map(Integral)
                 },
                 Some(ty_hint) => panic!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
             }
         },
-        LitKind::Int(n @ 0...U8MAX, Unsigned(UintTy::U8)) => Ok(Integral(U8(n as u8))),
-        LitKind::Int(n @ 0...U16MAX, Unsigned(UintTy::U16)) => Ok(Integral(U16(n as u16))),
-        LitKind::Int(n @ 0...U32MAX, Unsigned(UintTy::U32)) => Ok(Integral(U32(n as u32))),
-        LitKind::Int(n @ 0...U64MAX, Unsigned(UintTy::U64)) => Ok(Integral(U64(n as u64))),
-
-        LitKind::Int(n, Unsigned(UintTy::Us)) => {
-            Ok(Integral(Usize(try!(ConstUsize::new(n as u64, tcx.sess.target.uint_type)))))
+        LitKind::Int(n, Unsigned(ity)) => {
+            infer(Infer(n), tcx, &ty::TyUint(ity), span).map(Integral)
         },
-        LitKind::Int(_, Unsigned(ty)) => Err(ConstMathErr::ULitOutOfRange(ty)),
 
         LitKind::Float(ref n, _) |
         LitKind::FloatUnsuffixed(ref n) => {
index bb72711379eaa35ff6e124b22eea4a31580f7d80..15253987bf2b230b2bd1b7276932b60478a41a4d 100644 (file)
@@ -73,11 +73,11 @@ pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {
             (_, InferSigned(_))
             | (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)),
 
-            (Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i8),
-            (Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i16),
-            (Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i32),
+            (Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8),
+            (Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16),
+            (Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32),
             (Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64),
-            (Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i32)),
+            (Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
             (Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
             (Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8),
             (Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16),
index a25d0a9e1871fdd1ded7a64c6100240acdeac2d4..d66716c14c3d5ee15b42e1ffb75ebc72fe691219 100644 (file)
@@ -8,32 +8,35 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(overflowing_literals)]
+#![allow(dead_code)]
+
 #[repr(i8)]
 enum Ei8 {
     Ai8 = 23,
     Bi8 = -23,
-    Ci8 = 223, //~ ERROR literal out of range for i8 [E0080]
+    Ci8 = 223, //~ ERROR literal out of range for i8
 }
 
 #[repr(i16)]
 enum Ei16 {
     Ai16 = 23,
     Bi16 = -22333,
-    Ci16 = 55555, //~ ERROR literal out of range for i16 [E0080]
+    Ci16 = 55555, //~ ERROR literal out of range for i16
 }
 
 #[repr(i32)]
 enum Ei32 {
     Ai32 = 23,
     Bi32 = -2_000_000_000,
-    Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32 [E0080]
+    Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32
 }
 
 #[repr(i64)]
 enum Ei64 {
     Ai64 = 23,
     Bi64 = -9223372036854775808,
-    Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64 [E0080]
+    Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64
 }
 
 // u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`.  This is a
index 20e756c803a9c65757b63d4d39f6a026f9f6797d..8fc18d16469e37d3356736bff1cccd097005c0dc 100644 (file)
@@ -19,5 +19,6 @@ fn bar() -> i8 {
 }
 
 fn baz() -> bool {
-    128 > bar() //~ ERROR literal out of range for i8
+    128 > bar() //~ ERROR comparison is useless due to type limits
+                //~| WARN literal out of range for i8
 }
index fed4143a6d7a2b1571fffd429684646717c54e27..b09dc0acdbf91f41e9f50551a6c7f2c8893d7b15 100644 (file)
@@ -15,7 +15,8 @@ fn main() { }
 
 fn qux() {
     let mut i = 1i8;
-    while 200 != i { //~ ERROR literal out of range for i8
+    while 200 != i { //~ ERROR comparison is useless due to type limits
+                     //~| WARN literal out of range for i8
         i += 1;
     }
 }
index afd82e7d8aced0ebdc8f53e4a6c5f74bd01fd7fb..96f4217e4cb8023f6c9b6ac4bc9435484a7cb062 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(stmt_expr_attributes)]
+
 #[deny(const_err)]
 
 fn main() {
@@ -18,7 +20,10 @@ fn main() {
     assert_eq!(::std::i32::MIN as u64, 0xffffffff80000000);
     assert_eq!(-2147483648isize as u64, 0xffffffff80000000);
     assert_eq!(::std::i64::MIN as u64, 0x8000000000000000);
+    #[cfg(target_pointer_width = "64")]
     assert_eq!(-9223372036854775808isize as u64, 0x8000000000000000);
+    #[cfg(target_pointer_width = "32")]
+    assert_eq!(-9223372036854775808isize as u64, 0);
     const J: usize = ::std::i32::MAX as usize;
     const K: usize = -1i32 as u32 as usize;
     const L: usize = ::std::i32::MIN as usize;