about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_const_eval/eval.rs29
-rw-r--r--src/librustc_const_math/int.rs2
-rw-r--r--src/test/run-pass/issue-38987.rs14
3 files changed, 31 insertions, 14 deletions
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index bc72c8fb9b6..c899d2109f5 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -464,33 +464,36 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
         if let hir::ExprLit(ref lit) = inner.node {
             use syntax::ast::*;
             use syntax::ast::LitIntType::*;
-            const I8_OVERFLOW: u128 = i8::max_value() as u128 + 1;
-            const I16_OVERFLOW: u128 = i16::max_value() as u128 + 1;
-            const I32_OVERFLOW: u128 = i32::max_value() as u128 + 1;
-            const I64_OVERFLOW: u128 = i64::max_value() as u128 + 1;
-            const I128_OVERFLOW: u128 = i128::max_value() as u128 + 1;
+            const I8_OVERFLOW: u128 = i8::min_value() as u8 as u128;
+            const I16_OVERFLOW: u128 = i16::min_value() as u16 as u128;
+            const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128;
+            const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128;
+            const I128_OVERFLOW: u128 = i128::min_value() as u128;
             match (&lit.node, ety.map(|t| &t.sty)) {
-                (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) |
+                (&LitKind::Int(I8_OVERFLOW, _), Some(&ty::TyInt(IntTy::I8))) |
                 (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
                     return Ok(Integral(I8(i8::min_value())))
                 },
-                (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) |
+                (&LitKind::Int(I16_OVERFLOW, _), Some(&ty::TyInt(IntTy::I16))) |
                 (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
                     return Ok(Integral(I16(i16::min_value())))
                 },
-                (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) |
+                (&LitKind::Int(I32_OVERFLOW, _), Some(&ty::TyInt(IntTy::I32))) |
                 (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
                     return Ok(Integral(I32(i32::min_value())))
                 },
-                (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) |
+                (&LitKind::Int(I64_OVERFLOW, _), Some(&ty::TyInt(IntTy::I64))) |
                 (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
                     return Ok(Integral(I64(i64::min_value())))
                 },
-                (&LitKind::Int(I128_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I128))) |
-                (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
-                    return Ok(Integral(I128(i128::min_value())))
+                (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::I128))) |
+                (&LitKind::Int(n, Signed(IntTy::I128)), _) => {
+                    // SNAP: replace n in pattern with I128_OVERFLOW and remove this if.
+                    if n == I128_OVERFLOW {
+                        return Ok(Integral(I128(i128::min_value())))
+                    }
                 },
-                (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) |
+                (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::Is))) |
                 (&LitKind::Int(n, Signed(IntTy::Is)), _) => {
                     match tcx.sess.target.int_type {
                         IntTy::I16 => if n == I16_OVERFLOW {
diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs
index 59eb4b70aa8..53f185b661b 100644
--- a/src/librustc_const_math/int.rs
+++ b/src/librustc_const_math/int.rs
@@ -661,7 +661,7 @@ impl ::std::ops::Neg for ConstInt {
             a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) |
             a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a),
             U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation),
-            Infer(a @ 0...ubounds::I64MAX) => Ok(InferSigned(-(a as i128))),
+            Infer(a @ 0...ubounds::I128MAX) => Ok(InferSigned(-(a as i128))),
             Infer(_) => Err(Overflow(Op::Neg)),
             InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))),
         }
diff --git a/src/test/run-pass/issue-38987.rs b/src/test/run-pass/issue-38987.rs
new file mode 100644
index 00000000000..a513476d4a3
--- /dev/null
+++ b/src/test/run-pass/issue-38987.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(i128_type)]
+
+fn main() {
+    let _ = -0x8000_0000_0000_0000_0000_0000_0000_0000i128;
+}