diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index bc72c8fb9b6fe..c899d2109f51c 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 59eb4b70aa8ff..53f185b661b41 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 0000000000000..a513476d4a33a --- /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 or the MIT license +// , 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; +}