From 21c2b714056f5c6fee634b87f3f4c05ac1a85bec Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:17:05 +0200 Subject: [PATCH 01/16] Remove unused error variants --- src/librustc/ich/impls_const_math.rs | 5 ----- src/librustc/middle/const_val.rs | 5 +---- src/librustc_const_math/err.rs | 22 ---------------------- 3 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 5f3ff461c0c7e..afa28ae319cba 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -17,16 +17,11 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { }); impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - NotInRange, CmpBetweenUnequalTypes, UnequalTypes(op), Overflow(op), - ShiftNegative, DivisionByZero, RemainderByZero, - UnsignedNegation, - ULitOutOfRange(int_ty), - LitOutOfRange(int_ty) }); impl_stable_hash_for!(enum ::rustc_const_math::Op { diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 19a7576b7ceac..8a2126e356f86 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -78,10 +78,7 @@ pub struct FrameInfo { impl<'tcx> From for ErrKind<'tcx> { fn from(err: ConstMathErr) -> ErrKind<'tcx> { - match err { - ConstMathErr::UnsignedNegation => ErrKind::TypeckError, - _ => ErrKind::Math(err) - } + ErrKind::Math(err) } } diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index bd0a332436e64..dee8813e86f28 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -8,20 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast; - #[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] pub enum ConstMathErr { - NotInRange, CmpBetweenUnequalTypes, UnequalTypes(Op), Overflow(Op), - ShiftNegative, DivisionByZero, RemainderByZero, - UnsignedNegation, - ULitOutOfRange(ast::UintTy), - LitOutOfRange(ast::IntTy), } pub use self::ConstMathErr::*; @@ -44,7 +37,6 @@ impl ConstMathErr { pub fn description(&self) -> &'static str { use self::Op::*; match *self { - NotInRange => "inferred value out of range", CmpBetweenUnequalTypes => "compared two values of different types", UnequalTypes(Add) => "tried to add two values of different types", UnequalTypes(Sub) => "tried to subtract two values of different types", @@ -66,22 +58,8 @@ impl ConstMathErr { Overflow(Shr) => "attempt to shift right with overflow", Overflow(Shl) => "attempt to shift left with overflow", Overflow(_) => unreachable!(), - ShiftNegative => "attempt to shift by a negative amount", DivisionByZero => "attempt to divide by zero", RemainderByZero => "attempt to calculate the remainder with a divisor of zero", - UnsignedNegation => "unary negation of unsigned integer", - ULitOutOfRange(ast::UintTy::U8) => "literal out of range for u8", - ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16", - ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32", - ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64", - ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128", - ULitOutOfRange(ast::UintTy::Usize) => "literal out of range for usize", - LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8", - LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16", - LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32", - LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64", - LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128", - LitOutOfRange(ast::IntTy::Isize) => "literal out of range for isize", } } } From 7def638e42b70ee204cc84458b3d3775bbeba055 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:36:16 +0200 Subject: [PATCH 02/16] Comment typo --- src/librustc_apfloat/ppc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs index dec88eb62cc60..e662088e82fb0 100644 --- a/src/librustc_apfloat/ppc.rs +++ b/src/librustc_apfloat/ppc.rs @@ -20,7 +20,7 @@ use std::ops::Neg; pub struct DoubleFloat(F, F); pub type DoubleDouble = DoubleFloat; -// These are legacy semantics for the Fallback, inaccrurate implementation of +// These are legacy semantics for the Fallback, inaccurate implementation of // IBM double-double, if the accurate DoubleDouble doesn't handle the // operation. It's equivalent to having an IEEE number with consecutive 106 // bits of mantissa and 11 bits of exponent. From 7d982fdcf439799efbcc9f0cfcda99fa87b07460 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:42:30 +0200 Subject: [PATCH 03/16] Implement `PartialCmp` for `ConstFloat` --- src/librustc/ich/impls_const_math.rs | 1 - src/librustc_const_math/err.rs | 2 -- src/librustc_const_math/float.rs | 14 ++++++++++---- src/librustc_mir/hair/pattern/mod.rs | 3 +-- src/librustc_mir/interpret/operator.rs | 12 ++++++------ 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index afa28ae319cba..387a6d5f35c44 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -17,7 +17,6 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { }); impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - CmpBetweenUnequalTypes, UnequalTypes(op), Overflow(op), DivisionByZero, diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index dee8813e86f28..5d442ee7b9721 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -10,7 +10,6 @@ #[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] pub enum ConstMathErr { - CmpBetweenUnequalTypes, UnequalTypes(Op), Overflow(Op), DivisionByZero, @@ -37,7 +36,6 @@ impl ConstMathErr { pub fn description(&self) -> &'static str { use self::Op::*; match *self { - CmpBetweenUnequalTypes => "compared two values of different types", UnequalTypes(Add) => "tried to add two values of different types", UnequalTypes(Sub) => "tried to subtract two values of different types", UnequalTypes(Mul) => "tried to multiply two values of different types", diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs index 9d820ea8cbed2..61e9b34f06a2c 100644 --- a/src/librustc_const_math/float.rs +++ b/src/librustc_const_math/float.rs @@ -31,6 +31,12 @@ pub struct ConstFloat { pub bits: u128, } +impl PartialOrd for ConstFloat { + fn partial_cmp(&self, other: &Self) -> Option { + self.try_cmp(*other) + } +} + impl ConstFloat { /// Description of the type, not the value pub fn description(&self) -> &'static str { @@ -38,22 +44,22 @@ impl ConstFloat { } /// Compares the values if they are of the same type - pub fn try_cmp(self, rhs: Self) -> Result { + fn try_cmp(self, rhs: Self) -> Option { match (self.ty, rhs.ty) { (ast::FloatTy::F64, ast::FloatTy::F64) => { let a = Double::from_bits(self.bits); let b = Double::from_bits(rhs.bits); // This is pretty bad but it is the existing behavior. - Ok(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) + Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) } (ast::FloatTy::F32, ast::FloatTy::F32) => { let a = Single::from_bits(self.bits); let b = Single::from_bits(rhs.bits); - Ok(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) + Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) } - _ => Err(CmpBetweenUnequalTypes), + _ => None, } } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index c2da8c11d87e9..776b24a8648e7 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -1069,8 +1069,7 @@ pub fn compare_const_vals<'a, 'tcx>( bits: b, ty, }; - // FIXME(oli-obk): report cmp errors? - l.try_cmp(r).ok() + l.partial_cmp(&r) }, ty::TyInt(_) => { let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt"); diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index dfc0c4a824a84..0c748f818ccc8 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -135,12 +135,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { ty, }; match op { - Eq => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Equal), - Ne => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Equal), - Lt => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Less), - Le => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Greater), - Gt => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Greater), - Ge => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Less), + Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Equal), + Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Equal), + Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Less), + Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Greater), + Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Greater), + Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Less), Add => PrimVal::Bytes((l + r).unwrap().bits), Sub => PrimVal::Bytes((l - r).unwrap().bits), Mul => PrimVal::Bytes((l * r).unwrap().bits), From 0aa6e039d013e2c3800884a19e53e3f6c927a0e8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:55:34 +0200 Subject: [PATCH 04/16] Remove the `UnequalTypes` error variant --- src/librustc/ich/impls_const_math.rs | 1 - src/librustc_const_math/err.rs | 12 ------------ src/librustc_const_math/float.rs | 10 ++++------ 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 387a6d5f35c44..494fa49b53de9 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -17,7 +17,6 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { }); impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - UnequalTypes(op), Overflow(op), DivisionByZero, RemainderByZero, diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index 5d442ee7b9721..94a51c23a5ea6 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -10,7 +10,6 @@ #[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] pub enum ConstMathErr { - UnequalTypes(Op), Overflow(Op), DivisionByZero, RemainderByZero, @@ -36,17 +35,6 @@ impl ConstMathErr { pub fn description(&self) -> &'static str { use self::Op::*; match *self { - UnequalTypes(Add) => "tried to add two values of different types", - UnequalTypes(Sub) => "tried to subtract two values of different types", - UnequalTypes(Mul) => "tried to multiply two values of different types", - UnequalTypes(Div) => "tried to divide two values of different types", - UnequalTypes(Rem) => { - "tried to calculate the remainder of two values of different types" - }, - UnequalTypes(BitAnd) => "tried to bitand two values of different types", - UnequalTypes(BitOr) => "tried to bitor two values of different types", - UnequalTypes(BitXor) => "tried to xor two values of different types", - UnequalTypes(_) => unreachable!(), Overflow(Add) => "attempt to add with overflow", Overflow(Sub) => "attempt to subtract with overflow", Overflow(Mul) => "attempt to multiply with overflow", diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs index 61e9b34f06a2c..35cfe466c8a73 100644 --- a/src/librustc_const_math/float.rs +++ b/src/librustc_const_math/float.rs @@ -16,8 +16,6 @@ use syntax::ast; use rustc_apfloat::{Float, FloatConvert, Status}; use rustc_apfloat::ieee::{Single, Double}; -use super::err::*; - // Note that equality for `ConstFloat` means that the it is the same // constant, not that the rust values are equal. In particular, `NaN // == NaN` (at least if it's the same NaN; distinct encodings for NaN @@ -172,8 +170,8 @@ impl ::std::fmt::Debug for ConstFloat { macro_rules! derive_binop { ($op:ident, $func:ident) => { impl ::std::ops::$op for ConstFloat { - type Output = Result; - fn $func(self, rhs: Self) -> Result { + type Output = Option; + fn $func(self, rhs: Self) -> Option { let bits = match (self.ty, rhs.ty) { (ast::FloatTy::F32, ast::FloatTy::F32) =>{ let a = Single::from_bits(self.bits); @@ -185,9 +183,9 @@ macro_rules! derive_binop { let b = Double::from_bits(rhs.bits); a.$func(b).value.to_bits() } - _ => return Err(UnequalTypes(Op::$op)), + _ => return None, }; - Ok(ConstFloat { bits, ty: self.ty }) + Some(ConstFloat { bits, ty: self.ty }) } } } From d1d8d999ba577ae03576403aa9124204dd630f63 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 15:09:09 +0200 Subject: [PATCH 05/16] Remove unused const error variant --- src/librustc/ich/impls_ty.rs | 3 --- src/librustc/middle/const_val.rs | 9 --------- src/librustc/ty/structural_impls.rs | 1 - 3 files changed, 13 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 5ab8d6eb7b3e0..f4d20f4c31aae 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -505,9 +505,6 @@ for ::middle::const_val::ErrKind<'gcx> { len.hash_stable(hcx, hasher); index.hash_stable(hcx, hasher); } - Math(ref const_math_err) => { - const_math_err.hash_stable(hcx, hasher); - } LayoutError(ref layout_error) => { layout_error.hash_stable(hcx, hasher); } diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 8a2126e356f86..0ecab50dda229 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -11,7 +11,6 @@ use hir::def_id::DefId; use ty::{self, TyCtxt, layout}; use ty::subst::Substs; -use rustc_const_math::*; use mir::interpret::{Value, PrimVal}; use errors::DiagnosticBuilder; @@ -62,7 +61,6 @@ pub enum ErrKind<'tcx> { UnimplementedConstVal(&'static str), IndexOutOfBounds { len: u64, index: u64 }, - Math(ConstMathErr), LayoutError(layout::LayoutError<'tcx>), TypeckError, @@ -76,12 +74,6 @@ pub struct FrameInfo { pub location: String, } -impl<'tcx> From for ErrKind<'tcx> { - fn from(err: ConstMathErr) -> ErrKind<'tcx> { - ErrKind::Math(err) - } -} - #[derive(Clone, Debug)] pub enum ConstEvalErrDescription<'a, 'tcx: 'a> { Simple(Cow<'a, str>), @@ -119,7 +111,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { len, index) } - Math(ref err) => Simple(err.description().into_cow()), LayoutError(ref err) => Simple(err.to_string().into_cow()), TypeckError => simple!("type-checking failed"), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 9b20fce667318..f81617a3795a7 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -585,7 +585,6 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> { NonConstPath => NonConstPath, UnimplementedConstVal(s) => UnimplementedConstVal(s), IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index }, - Math(ref e) => Math(e.clone()), LayoutError(ref e) => { return tcx.lift(e).map(LayoutError) From a9366aa874a29467014c2eef96234455509aa438 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 15:35:58 +0200 Subject: [PATCH 06/16] Remove unused const math ops --- src/librustc/ich/impls_const_math.rs | 3 --- src/librustc_const_math/err.rs | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 494fa49b53de9..3c1205a67843d 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -31,7 +31,4 @@ impl_stable_hash_for!(enum ::rustc_const_math::Op { Shr, Shl, Neg, - BitAnd, - BitOr, - BitXor }); diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index 94a51c23a5ea6..552932993ecf8 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -26,9 +26,6 @@ pub enum Op { Shr, Shl, Neg, - BitAnd, - BitOr, - BitXor, } impl ConstMathErr { @@ -43,7 +40,6 @@ impl ConstMathErr { Overflow(Neg) => "attempt to negate with overflow", Overflow(Shr) => "attempt to shift right with overflow", Overflow(Shl) => "attempt to shift left with overflow", - Overflow(_) => unreachable!(), DivisionByZero => "attempt to divide by zero", RemainderByZero => "attempt to calculate the remainder with a divisor of zero", } From f45d0f3783ec2a03a34712392d9d5e42067690dc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 15:36:25 +0200 Subject: [PATCH 07/16] Removed unused dependencies on rustc_const_math --- src/librustc_passes/Cargo.toml | 1 - src/librustc_passes/lib.rs | 1 - src/librustc_typeck/Cargo.toml | 1 - src/librustc_typeck/lib.rs | 1 - src/librustdoc/lib.rs | 1 - 5 files changed, 5 deletions(-) diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 4bab24ae1392c..2babb93eedbcf 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -12,7 +12,6 @@ crate-type = ["dylib"] log = "0.4" rustc = { path = "../librustc" } rustc_mir = { path = "../librustc_mir"} -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index e65c9de8df1ea..b6b5edc094003 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -23,7 +23,6 @@ #[macro_use] extern crate rustc; extern crate rustc_mir; -extern crate rustc_const_math; extern crate rustc_data_structures; #[macro_use] diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 70c13e9b7d637..c426533779c9b 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -15,7 +15,6 @@ syntax = { path = "../libsyntax" } arena = { path = "../libarena" } fmt_macros = { path = "../libfmt_macros" } rustc = { path = "../librustc" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 958960d3a36fd..350b53a406bc8 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -92,7 +92,6 @@ extern crate syntax_pos; extern crate arena; #[macro_use] extern crate rustc; extern crate rustc_platform_intrinsics as intrinsics; -extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_errors as errors; extern crate rustc_target; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8efb51bccd805..059d41698953d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,7 +31,6 @@ extern crate getopts; extern crate env_logger; extern crate rustc; extern crate rustc_data_structures; -extern crate rustc_const_math; extern crate rustc_trans_utils; extern crate rustc_driver; extern crate rustc_resolve; From 40b118cf4767413f7676c97296c222167604485b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 25 Apr 2018 15:26:12 +0200 Subject: [PATCH 08/16] Remove ConstFloat --- src/librustc/ich/impls_const_math.rs | 5 - src/librustc/mir/mod.rs | 9 +- src/librustc_const_math/float.rs | 217 ------------------------- src/librustc_const_math/lib.rs | 5 - src/librustc_mir/hair/cx/mod.rs | 24 +-- src/librustc_mir/hair/pattern/mod.rs | 66 +++++--- src/librustc_mir/interpret/cast.rs | 9 +- src/librustc_mir/interpret/operator.rs | 54 +++--- src/librustc_trans/mir/rvalue.rs | 5 +- 9 files changed, 85 insertions(+), 309 deletions(-) delete mode 100644 src/librustc_const_math/float.rs diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 3c1205a67843d..bbc43987c99de 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -11,11 +11,6 @@ //! This module contains `HashStable` implementations for various data types //! from `rustc_const_math` in no particular order. -impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { - ty, - bits -}); - impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { Overflow(op), DivisionByZero, diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c26b3014e53dd..d1e515b2c7767 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -43,6 +43,8 @@ use std::vec::IntoIter; use syntax::ast::{self, Name}; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; +use rustc_apfloat::ieee::{Single, Double}; +use rustc_apfloat::Float; mod cache; pub mod tcx; @@ -1915,12 +1917,13 @@ fn fmt_const_val(fmt: &mut W, const_val: &ty::Const) -> fmt::Result { pub fn print_miri_value(value: Value, ty: Ty, f: &mut W) -> fmt::Result { use ty::TypeVariants::*; - use rustc_const_math::ConstFloat; match (value, &ty.sty) { (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"), (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"), - (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(fty)) => - write!(f, "{}", ConstFloat { bits, ty: fty }), + (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) => + write!(f, "{}", Single::from_bits(bits)), + (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) => + write!(f, "{}", Double::from_bits(bits)), (Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui), (Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i), (Value::ByVal(PrimVal::Bytes(n)), &TyChar) => diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs deleted file mode 100644 index 35cfe466c8a73..0000000000000 --- a/src/librustc_const_math/float.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2015 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. - -use std::cmp::Ordering; -use std::num::ParseFloatError; - -use syntax::ast; - -use rustc_apfloat::{Float, FloatConvert, Status}; -use rustc_apfloat::ieee::{Single, Double}; - -// Note that equality for `ConstFloat` means that the it is the same -// constant, not that the rust values are equal. In particular, `NaN -// == NaN` (at least if it's the same NaN; distinct encodings for NaN -// are considering unequal). -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct ConstFloat { - pub ty: ast::FloatTy, - - // This is a bit inefficient but it makes conversions below more - // ergonomic, and all of this will go away once `miri` is merged. - pub bits: u128, -} - -impl PartialOrd for ConstFloat { - fn partial_cmp(&self, other: &Self) -> Option { - self.try_cmp(*other) - } -} - -impl ConstFloat { - /// Description of the type, not the value - pub fn description(&self) -> &'static str { - self.ty.ty_to_string() - } - - /// Compares the values if they are of the same type - fn try_cmp(self, rhs: Self) -> Option { - match (self.ty, rhs.ty) { - (ast::FloatTy::F64, ast::FloatTy::F64) => { - let a = Double::from_bits(self.bits); - let b = Double::from_bits(rhs.bits); - // This is pretty bad but it is the existing behavior. - Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) - } - - (ast::FloatTy::F32, ast::FloatTy::F32) => { - let a = Single::from_bits(self.bits); - let b = Single::from_bits(rhs.bits); - Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) - } - - _ => None, - } - } - - pub fn from_i128(input: i128, ty: ast::FloatTy) -> Self { - let bits = match ty { - ast::FloatTy::F32 => Single::from_i128(input).value.to_bits(), - ast::FloatTy::F64 => Double::from_i128(input).value.to_bits() - }; - ConstFloat { bits, ty } - } - - pub fn from_u128(input: u128, ty: ast::FloatTy) -> Self { - let bits = match ty { - ast::FloatTy::F32 => Single::from_u128(input).value.to_bits(), - ast::FloatTy::F64 => Double::from_u128(input).value.to_bits() - }; - ConstFloat { bits, ty } - } - - pub fn from_str(num: &str, ty: ast::FloatTy) -> Result { - let bits = match ty { - ast::FloatTy::F32 => { - let rust_bits = num.parse::()?.to_bits() as u128; - let apfloat = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e); - }); - let apfloat_bits = apfloat.to_bits(); - assert!(rust_bits == apfloat_bits, - "apfloat::ieee::Single gave different result for `{}`: \ - {}({:#x}) vs Rust's {}({:#x})", - num, apfloat, apfloat_bits, - Single::from_bits(rust_bits), rust_bits); - apfloat_bits - } - ast::FloatTy::F64 => { - let rust_bits = num.parse::()?.to_bits() as u128; - let apfloat = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e); - }); - let apfloat_bits = apfloat.to_bits(); - assert!(rust_bits == apfloat_bits, - "apfloat::ieee::Double gave different result for `{}`: \ - {}({:#x}) vs Rust's {}({:#x})", - num, apfloat, apfloat_bits, - Double::from_bits(rust_bits), rust_bits); - apfloat_bits - } - }; - Ok(ConstFloat { bits, ty }) - } - - pub fn to_i128(self, width: usize) -> Option { - assert!(width <= 128); - let r = match self.ty { - ast::FloatTy::F32 => Single::from_bits(self.bits).to_i128(width), - ast::FloatTy::F64 => Double::from_bits(self.bits).to_i128(width) - }; - if r.status.intersects(Status::INVALID_OP) { - None - } else { - Some(r.value) - } - } - - pub fn to_u128(self, width: usize) -> Option { - assert!(width <= 128); - let r = match self.ty { - ast::FloatTy::F32 => Single::from_bits(self.bits).to_u128(width), - ast::FloatTy::F64 => Double::from_bits(self.bits).to_u128(width) - }; - if r.status.intersects(Status::INVALID_OP) { - None - } else { - Some(r.value) - } - } - - pub fn convert(self, to: ast::FloatTy) -> Self { - let bits = match (self.ty, to) { - (ast::FloatTy::F32, ast::FloatTy::F32) | - (ast::FloatTy::F64, ast::FloatTy::F64) => return self, - - (ast::FloatTy::F32, ast::FloatTy::F64) => { - Double::to_bits(Single::from_bits(self.bits).convert(&mut false).value) - } - (ast::FloatTy::F64, ast::FloatTy::F32) => { - Single::to_bits(Double::from_bits(self.bits).convert(&mut false).value) - } - }; - ConstFloat { bits, ty: to } - } -} - -impl ::std::fmt::Display for ConstFloat { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - match self.ty { - ast::FloatTy::F32 => write!(fmt, "{:#}", Single::from_bits(self.bits))?, - ast::FloatTy::F64 => write!(fmt, "{:#}", Double::from_bits(self.bits))?, - } - write!(fmt, "{}", self.ty) - } -} - -impl ::std::fmt::Debug for ConstFloat { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(self, fmt) - } -} - -macro_rules! derive_binop { - ($op:ident, $func:ident) => { - impl ::std::ops::$op for ConstFloat { - type Output = Option; - fn $func(self, rhs: Self) -> Option { - let bits = match (self.ty, rhs.ty) { - (ast::FloatTy::F32, ast::FloatTy::F32) =>{ - let a = Single::from_bits(self.bits); - let b = Single::from_bits(rhs.bits); - a.$func(b).value.to_bits() - } - (ast::FloatTy::F64, ast::FloatTy::F64) => { - let a = Double::from_bits(self.bits); - let b = Double::from_bits(rhs.bits); - a.$func(b).value.to_bits() - } - _ => return None, - }; - Some(ConstFloat { bits, ty: self.ty }) - } - } - } -} - -derive_binop!(Add, add); -derive_binop!(Sub, sub); -derive_binop!(Mul, mul); -derive_binop!(Div, div); -derive_binop!(Rem, rem); - -impl ::std::ops::Neg for ConstFloat { - type Output = Self; - fn neg(self) -> Self { - let bits = match self.ty { - ast::FloatTy::F32 => (-Single::from_bits(self.bits)).to_bits(), - ast::FloatTy::F64 => (-Double::from_bits(self.bits)).to_bits(), - }; - ConstFloat { bits, ty: self.ty } - } -} - -/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this -/// are rounded to infinity when converted to `f32`. -/// -/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP) -/// shifted by the maximum exponent (accounting for normalization). -pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1) - << (Single::MAX_EXP - Single::PRECISION as i16); diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 499c330be1da8..08996b892f9a6 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -18,14 +18,9 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -extern crate rustc_apfloat; - -extern crate syntax; extern crate serialize as rustc_serialize; // used by deriving -mod float; mod err; -pub use float::*; pub use err::{ConstMathErr, Op}; diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index e6aa2d3abb7e0..ff5c808459190 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -30,9 +30,9 @@ use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; -use rustc_const_math::ConstFloat; use rustc_data_structures::sync::Lrc; use rustc::mir::interpret::{Value, PrimVal}; +use hair::pattern::parse_float; #[derive(Clone)] pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -170,14 +170,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { neg: bool, ) -> Literal<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); - let tcx = self.tcx.global_tcx(); - - let parse_float = |num: &str, fty| -> ConstFloat { - ConstFloat::from_str(num, fty).unwrap_or_else(|_| { - // FIXME(#31407) this is only necessary because float parsing is buggy - tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); - }) - }; let clamp = |n| { let size = self.integer_bit_width(ty); @@ -214,12 +206,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))), LitKind::Float(n, fty) => { let n = n.as_str(); - let mut f = parse_float(&n, fty); - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).expect("apfloat parsing failed") } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { @@ -227,12 +214,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { _ => bug!() }; let n = n.as_str(); - let mut f = parse_float(&n, fty); - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).expect("apfloat parsing failed") } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 776b24a8648e7..590cc77c46d77 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -28,7 +28,6 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc_data_structures::indexed_vec::Idx; -use rustc_const_math::ConstFloat; use std::cmp::Ordering; use std::fmt; @@ -1053,22 +1052,21 @@ pub fn compare_const_vals<'a, 'tcx>( b: &ConstVal, ty: Ty<'tcx>, ) -> Option { - use rustc_const_math::ConstFloat; trace!("compare_const_vals: {:?}, {:?}", a, b); use rustc::mir::interpret::{Value, PrimVal}; match (a, b) { (&ConstVal::Value(Value::ByVal(PrimVal::Bytes(a))), &ConstVal::Value(Value::ByVal(PrimVal::Bytes(b)))) => { + use ::rustc_apfloat::Float; match ty.sty { - ty::TyFloat(ty) => { - let l = ConstFloat { - bits: a, - ty, - }; - let r = ConstFloat { - bits: b, - ty, - }; + ty::TyFloat(ast::FloatTy::F32) => { + let l = ::rustc_apfloat::ieee::Single::from_bits(a); + let r = ::rustc_apfloat::ieee::Single::from_bits(b); + l.partial_cmp(&r) + }, + ty::TyFloat(ast::FloatTy::F64) => { + let l = ::rustc_apfloat::ieee::Double::from_bits(a); + let r = ::rustc_apfloat::ieee::Double::from_bits(b); l.partial_cmp(&r) }, ty::TyInt(_) => { @@ -1148,12 +1146,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, }, LitKind::Float(n, fty) => { let n = n.as_str(); - let mut f = parse_float(&n, fty)?; - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).map_err(|_| ())? } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { @@ -1161,12 +1154,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, _ => bug!() }; let n = n.as_str(); - let mut f = parse_float(&n, fty)?; - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).map_err(|_| ())? } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), @@ -1174,7 +1162,33 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, Ok(ConstVal::Value(lit)) } -fn parse_float<'tcx>(num: &str, fty: ast::FloatTy) - -> Result { - ConstFloat::from_str(num, fty).map_err(|_| ()) +pub fn parse_float( + num: &str, + fty: ast::FloatTy, + neg: bool, +) -> Result { + use rustc_apfloat::ieee::{Single, Double}; + use rustc_apfloat::Float; + let bits = match fty { + ast::FloatTy::F32 => { + let mut f = num.parse::().map_err(|e| { + format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + })?; + if neg { + f = -f; + } + f.to_bits() + } + ast::FloatTy::F64 => { + let mut f = num.parse::().map_err(|e| { + format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + })?; + if neg { + f = -f; + } + f.to_bits() + } + }; + + Ok(Value::ByVal(PrimVal::Bytes(bits))) } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index e654142d2164c..002b5eb187db3 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -2,10 +2,9 @@ use rustc::ty::Ty; use rustc::ty::layout::LayoutOf; use syntax::ast::{FloatTy, IntTy, UintTy}; -use rustc_const_math::ConstFloat; +use rustc_apfloat::ieee::{Single, Double}; use super::{EvalContext, Machine}; use rustc::mir::interpret::{PrimVal, EvalResult, MemoryPointer, PointerArithmetic}; -use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { @@ -50,8 +49,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Ok(PrimVal::Bytes(v)) } - TyFloat(fty) if signed => Ok(PrimVal::Bytes(ConstFloat::from_i128(v as i128, fty).bits)), - TyFloat(fty) => Ok(PrimVal::Bytes(ConstFloat::from_u128(v, fty).bits)), + TyFloat(FloatTy::F32) if signed => Ok(PrimVal::Bytes(Single::from_i128(v as i128).value.to_bits())), + TyFloat(FloatTy::F64) if signed => Ok(PrimVal::Bytes(Double::from_i128(v as i128).value.to_bits())), + TyFloat(FloatTy::F32) => Ok(PrimVal::Bytes(Single::from_u128(v).value.to_bits())), + TyFloat(FloatTy::F64) => Ok(PrimVal::Bytes(Double::from_u128(v).value.to_bits())), TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)), TyChar => err!(InvalidChar(v)), diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 0c748f818ccc8..5a815e0dc67ef 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,9 +1,10 @@ use rustc::mir; use rustc::ty::{self, Ty}; -use rustc_const_math::ConstFloat; use syntax::ast::FloatTy; use std::cmp::Ordering; use rustc::ty::layout::LayoutOf; +use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; use super::{EvalContext, Place, Machine, ValTy}; @@ -125,31 +126,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { return err!(Unimplemented(msg)); } - let float_op = |op, l, r, ty| { - let l = ConstFloat { - bits: l, - ty, - }; - let r = ConstFloat { - bits: r, - ty, - }; - match op { - Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Equal), - Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Equal), - Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Less), - Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Greater), - Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Greater), - Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Less), - Add => PrimVal::Bytes((l + r).unwrap().bits), - Sub => PrimVal::Bytes((l - r).unwrap().bits), - Mul => PrimVal::Bytes((l * r).unwrap().bits), - Div => PrimVal::Bytes((l / r).unwrap().bits), - Rem => PrimVal::Bytes((l % r).unwrap().bits), - _ => bug!("invalid float op: `{:?}`", op), - } - }; - if left_layout.abi.is_signed() { let op: Option bool> = match bin_op { Lt => Some(i128::lt), @@ -199,7 +175,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } if let ty::TyFloat(fty) = left_ty.sty { - return Ok((float_op(bin_op, l, r, fty), false)); + macro_rules! float_math { + ($ty:path) => {{ + let l = <$ty>::from_bits(l); + let r = <$ty>::from_bits(r); + let val = match bin_op { + Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Equal), + Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Equal), + Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Less), + Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Greater), + Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Greater), + Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Less), + Add => PrimVal::Bytes((l + r).value.to_bits()), + Sub => PrimVal::Bytes((l - r).value.to_bits()), + Mul => PrimVal::Bytes((l * r).value.to_bits()), + Div => PrimVal::Bytes((l / r).value.to_bits()), + Rem => PrimVal::Bytes((l % r).value.to_bits()), + _ => bug!("invalid float op: `{:?}`", bin_op), + }; + return Ok((val, false)); + }}; + } + match fty { + FloatTy::F32 => float_math!(Single), + FloatTy::F64 => float_math!(Double), + } } // only ints left diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 79e906ca975fb..6e16590bf35a3 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -15,7 +15,6 @@ use rustc::ty::layout::{self, LayoutOf}; use rustc::mir; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; -use rustc_const_math::MAX_F32_PLUS_HALF_ULP; use std::{u128, i128}; use base; @@ -805,6 +804,10 @@ fn cast_int_to_float(bx: &Builder, if is_u128_to_f32 { // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity, // and for everything else LLVM's uitofp works just fine. + use rustc_apfloat::ieee::Single; + use rustc_apfloat::Float; + const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1) + << (Single::MAX_EXP - Single::PRECISION as i16); let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP); let overflow = bx.icmp(llvm::IntUGE, x, max); let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32); From cf103e56bd0bfdc3ef7202ba774a1981adb36a46 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 10:39:04 +0200 Subject: [PATCH 09/16] Reintroduce the float parsing error --- src/librustc_mir/hair/cx/mod.rs | 13 +++++++++---- src/librustc_mir/hair/pattern/mod.rs | 26 ++++++++++++++------------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index ff5c808459190..5890ea5c9d0c6 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -171,6 +171,13 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ) -> Literal<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); + let parse_float = |num, fty| -> Value { + parse_float(num, fty, neg).unwrap_or_else(|_| { + // FIXME(#31407) this is only necessary because float parsing is buggy + self.tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); + }) + }; + let clamp = |n| { let size = self.integer_bit_width(ty); trace!("clamp {} with size {} and amt {}", n, size, 128 - size); @@ -205,16 +212,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { }, LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))), LitKind::Float(n, fty) => { - let n = n.as_str(); - parse_float(&n, fty, neg).expect("apfloat parsing failed") + parse_float(n, fty) } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => bug!() }; - let n = n.as_str(); - parse_float(&n, fty, neg).expect("apfloat parsing failed") + parse_float(n, fty) } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 590cc77c46d77..619b4596b4227 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -34,6 +34,7 @@ use std::fmt; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; +use syntax_pos::symbol::Symbol; #[derive(Clone, Debug)] pub enum PatternError { @@ -1145,16 +1146,14 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, Value::ByVal(PrimVal::Bytes(n)) }, LitKind::Float(n, fty) => { - let n = n.as_str(); - parse_float(&n, fty, neg).map_err(|_| ())? + parse_float(n, fty, neg)? } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => bug!() }; - let n = n.as_str(); - parse_float(&n, fty, neg).map_err(|_| ())? + parse_float(n, fty, neg)? } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), @@ -1163,26 +1162,29 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, } pub fn parse_float( - num: &str, + num: Symbol, fty: ast::FloatTy, neg: bool, -) -> Result { +) -> Result { + let num = num.as_str(); use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; let bits = match fty { ast::FloatTy::F32 => { - let mut f = num.parse::().map_err(|e| { - format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - })?; + num.parse::().map_err(|_| ())?; + let mut f = num.parse::().unwrap_or_else(|e| { + panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + }); if neg { f = -f; } f.to_bits() } ast::FloatTy::F64 => { - let mut f = num.parse::().map_err(|e| { - format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - })?; + num.parse::().map_err(|_| ())?; + let mut f = num.parse::().unwrap_or_else(|e| { + panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + }); if neg { f = -f; } From 671b2a596439566b6614d2a7dd25643fc947c721 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 11:37:03 +0200 Subject: [PATCH 10/16] Remove the `rustc_const_math` crate --- src/librustc/Cargo.toml | 1 - src/librustc/ich/impls_const_math.rs | 29 --------------- src/librustc/ich/impls_ty.rs | 17 +++++++++ src/librustc/ich/mod.rs | 1 - src/librustc/lib.rs | 1 - src/librustc/mir/interpret/error.rs | 39 +++++++++++++++++++- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/mod.rs | 3 +- src/librustc_const_math/Cargo.toml | 14 ------- src/librustc_const_math/err.rs | 47 ------------------------ src/librustc_const_math/lib.rs | 26 ------------- src/librustc_mir/Cargo.toml | 1 - src/librustc_mir/build/expr/as_rvalue.rs | 3 +- src/librustc_mir/lib.rs | 2 - src/librustc_trans/Cargo.toml | 1 - src/librustc_trans/lib.rs | 1 - src/librustc_trans/mir/block.rs | 4 +- 17 files changed, 60 insertions(+), 132 deletions(-) delete mode 100644 src/librustc/ich/impls_const_math.rs delete mode 100644 src/librustc_const_math/Cargo.toml delete mode 100644 src/librustc_const_math/err.rs delete mode 100644 src/librustc_const_math/lib.rs diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 357ebb89fb652..af108188ce0f4 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -19,7 +19,6 @@ log = { version = "0.4", features = ["release_max_level_info", "std"] } proc_macro = { path = "../libproc_macro" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } serialize = { path = "../libserialize" } diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs deleted file mode 100644 index bbc43987c99de..0000000000000 --- a/src/librustc/ich/impls_const_math.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -//! This module contains `HashStable` implementations for various data types -//! from `rustc_const_math` in no particular order. - -impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - Overflow(op), - DivisionByZero, - RemainderByZero, -}); - -impl_stable_hash_for!(enum ::rustc_const_math::Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -}); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f4d20f4c31aae..92a8ee28168cf 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -669,6 +669,23 @@ for ::mir::interpret::EvalError<'gcx> { } } +impl_stable_hash_for!(enum mir::interpret::ConstMathErr { + Overflow(op), + DivisionByZero, + RemainderByZero, +}); + +impl_stable_hash_for!(enum mir::interpret::Op { + Add, + Sub, + Mul, + Div, + Rem, + Shr, + Shl, + Neg, +}); + impl_stable_hash_for!(enum mir::interpret::Lock { NoLock, WriteLock(dl), diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index 1b77a2e7c82b9..a0c6bbbb2393f 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -18,7 +18,6 @@ mod fingerprint; mod caching_codemap_view; mod hcx; -mod impls_const_math; mod impls_cstore; mod impls_hir; mod impls_mir; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24892dfcc8f7d..9c06c9055fbe9 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -85,7 +85,6 @@ extern crate libc; extern crate rustc_target; #[macro_use] extern crate rustc_data_structures; extern crate serialize; -extern crate rustc_const_math; extern crate rustc_errors as errors; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index b919f4d15a840..fff555a8976c3 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -8,7 +8,6 @@ use super::{ MemoryPointer, Lock, AccessKind }; -use rustc_const_math::ConstMathErr; use syntax::codemap::Span; use backtrace::Backtrace; @@ -304,3 +303,41 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { } } } + +#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] +pub enum ConstMathErr { + Overflow(Op), + DivisionByZero, + RemainderByZero, +} +pub use self::ConstMathErr::*; + +#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] +pub enum Op { + Add, + Sub, + Mul, + Div, + Rem, + Shr, + Shl, + Neg, +} + +impl ConstMathErr { + pub fn description(&self) -> &'static str { + use self::Op::*; + match *self { + Overflow(Add) => "attempt to add with overflow", + Overflow(Sub) => "attempt to subtract with overflow", + Overflow(Mul) => "attempt to multiply with overflow", + Overflow(Div) => "attempt to divide with overflow", + Overflow(Rem) => "attempt to calculate the remainder with overflow", + Overflow(Neg) => "attempt to negate with overflow", + Overflow(Shr) => "attempt to shift right with overflow", + Overflow(Shl) => "attempt to shift left with overflow", + DivisionByZero => "attempt to divide by zero", + RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + } + } +} diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index c9eed0e4a2885..fe29222e883ce 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -8,7 +8,7 @@ macro_rules! err { mod error; mod value; -pub use self::error::{EvalError, EvalResult, EvalErrorKind}; +pub use self::error::{EvalError, EvalResult, EvalErrorKind, Op, ConstMathErr}; pub use self::value::{PrimVal, PrimValKind, Value, Pointer}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d1e515b2c7767..3c4b9ae33519e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,6 @@ use graphviz::IntoCow; use middle::const_val::ConstVal; use middle::region; -use rustc_const_math::ConstMathErr; use rustc_data_structures::sync::{Lrc}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; @@ -26,7 +25,7 @@ use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; use mir::visit::MirVisitable; -use mir::interpret::{Value, PrimVal}; +use mir::interpret::{Value, PrimVal, ConstMathErr}; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml deleted file mode 100644 index 41310ede3e085..0000000000000 --- a/src/librustc_const_math/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rustc_const_math" -version = "0.0.0" - -[lib] -name = "rustc_const_math" -path = "lib.rs" -crate-type = ["dylib"] - -[dependencies] -rustc_apfloat = { path = "../librustc_apfloat" } -serialize = { path = "../libserialize" } -syntax = { path = "../libsyntax" } diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs deleted file mode 100644 index 552932993ecf8..0000000000000 --- a/src/librustc_const_math/err.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015 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. - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum ConstMathErr { - Overflow(Op), - DivisionByZero, - RemainderByZero, -} -pub use self::ConstMathErr::*; - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -} - -impl ConstMathErr { - pub fn description(&self) -> &'static str { - use self::Op::*; - match *self { - Overflow(Add) => "attempt to add with overflow", - Overflow(Sub) => "attempt to subtract with overflow", - Overflow(Mul) => "attempt to multiply with overflow", - Overflow(Div) => "attempt to divide with overflow", - Overflow(Rem) => "attempt to calculate the remainder with overflow", - Overflow(Neg) => "attempt to negate with overflow", - Overflow(Shr) => "attempt to shift right with overflow", - Overflow(Shl) => "attempt to shift left with overflow", - DivisionByZero => "attempt to divide by zero", - RemainderByZero => "attempt to calculate the remainder with a divisor of zero", - } - } -} diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs deleted file mode 100644 index 08996b892f9a6..0000000000000 --- a/src/librustc_const_math/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012-2013 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. - -//! Rusty Mathematics -//! -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] - - -extern crate serialize as rustc_serialize; // used by deriving - -mod err; - -pub use err::{ConstMathErr, Op}; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index a1b348774b163..62964745b6f9e 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -16,7 +16,6 @@ log = "0.4" log_settings = "0.1.1" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } serialize = { path = "../libserialize" } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index b7f402f61a9c1..a3798f3ed4c65 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -10,7 +10,6 @@ //! See docs in build/expr/mod.rs -use rustc_const_math::{ConstMathErr, Op}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -21,7 +20,7 @@ use rustc::middle::const_val::ConstVal; use rustc::middle::region; use rustc::ty::{self, Ty}; use rustc::mir::*; -use rustc::mir::interpret::{Value, PrimVal}; +use rustc::mir::interpret::{Value, PrimVal, ConstMathErr, Op}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 75b7a10097df4..97d1fb0a698b6 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -50,8 +50,6 @@ extern crate rustc_errors; extern crate syntax; extern crate syntax_pos; extern crate rustc_target; -extern crate rustc_const_math; -extern crate core; // for NonZero extern crate log_settings; extern crate rustc_apfloat; extern crate byteorder; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 32432d6cc835d..a4dd02e97b233 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -21,7 +21,6 @@ rustc-demangle = "0.1.4" rustc_allocator = { path = "../librustc_allocator" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_incremental = { path = "../librustc_incremental" } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 96a10e8b99d32..306f4179e4f57 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -43,7 +43,6 @@ extern crate rustc_mir; extern crate rustc_allocator; extern crate rustc_apfloat; extern crate rustc_target; -extern crate rustc_const_math; #[macro_use] extern crate rustc_data_structures; extern crate rustc_demangle; extern crate rustc_incremental; diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index e5fdc26eeaf0d..7c854ef04b7ca 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -311,8 +311,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.cx.check_overflow { - use rustc_const_math::ConstMathErr::Overflow; - use rustc_const_math::Op::Neg; + use rustc::mir::interpret::ConstMathErr::Overflow; + use rustc::mir::interpret::Op::Neg; if let mir::AssertMessage::Math(Overflow(Neg)) = *msg { const_cond = Some(expected); From cefcf0548ec06cfdd00de4d02ee9c1b0c6cfe6fa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 14:52:59 +0200 Subject: [PATCH 11/16] Merge ConstMathError into EvalErrorKind --- src/librustc/ich/impls_ty.rs | 42 +++++------- src/librustc/mir/interpret/error.rs | 72 ++++++-------------- src/librustc/mir/interpret/mod.rs | 12 ++-- src/librustc/mir/mod.rs | 8 +-- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/structural_impls.rs | 6 +- src/librustc_mir/build/expr/as_rvalue.rs | 23 ++----- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/operator.rs | 2 +- src/librustc_mir/interpret/terminator/mod.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_trans/mir/block.rs | 5 +- 12 files changed, 65 insertions(+), 115 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 92a8ee28168cf..a5447a3145afe 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -525,16 +525,26 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> { predicates }); + impl<'a, 'gcx> HashStable> for ::mir::interpret::EvalError<'gcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.kind.hash_stable(hcx, hasher) + } +} + +impl<'a, 'gcx> HashStable> +for ::mir::interpret::EvalErrorKind<'gcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { use mir::interpret::EvalErrorKind::*; - mem::discriminant(&self.kind).hash_stable(hcx, hasher); + mem::discriminant(&self).hash_stable(hcx, hasher); - match self.kind { + match *self { DanglingPointerDeref | DoubleFree | InvalidMemoryAccess | @@ -565,8 +575,10 @@ for ::mir::interpret::EvalError<'gcx> { TypeckError | DerefFunctionPointer | ExecuteMemory | - ReferencedConstant | - OverflowingMath => {} + OverflowNeg | + RemainderByZero | + DivisionByZero | + ReferencedConstant => {} MachineError(ref err) => err.hash_stable(hcx, hasher), FunctionPointerTyMismatch(a, b) => { a.hash_stable(hcx, hasher); @@ -590,10 +602,6 @@ for ::mir::interpret::EvalError<'gcx> { a.hash_stable(hcx, hasher); b.hash_stable(hcx, hasher) }, - Math(sp, ref err) => { - sp.hash_stable(hcx, hasher); - err.hash_stable(hcx, hasher) - }, Intrinsic(ref s) => s.hash_stable(hcx, hasher), InvalidChar(c) => c.hash_stable(hcx, hasher), AbiViolation(ref s) => s.hash_stable(hcx, hasher), @@ -665,27 +673,11 @@ for ::mir::interpret::EvalError<'gcx> { Layout(lay) => lay.hash_stable(hcx, hasher), HeapAllocNonPowerOfTwoAlignment(n) => n.hash_stable(hcx, hasher), PathNotFound(ref v) => v.hash_stable(hcx, hasher), + Overflow(op) => op.hash_stable(hcx, hasher), } } } -impl_stable_hash_for!(enum mir::interpret::ConstMathErr { - Overflow(op), - DivisionByZero, - RemainderByZero, -}); - -impl_stable_hash_for!(enum mir::interpret::Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -}); - impl_stable_hash_for!(enum mir::interpret::Lock { NoLock, WriteLock(dl), diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index fff555a8976c3..022b82841bcc2 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,4 +1,3 @@ -use std::error::Error; use std::{fmt, env}; use mir; @@ -30,7 +29,7 @@ impl<'tcx> From> for EvalError<'tcx> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, RustcEncodable, RustcDecodable)] pub enum EvalErrorKind<'tcx> { /// This variant is used by machines to signal their own errors that do not /// match an existing variant @@ -60,9 +59,11 @@ pub enum EvalErrorKind<'tcx> { DerefFunctionPointer, ExecuteMemory, ArrayIndexOutOfBounds(Span, u64, u64), - Math(Span, ConstMathErr), + Overflow(mir::BinOp), + OverflowNeg, + DivisionByZero, + RemainderByZero, Intrinsic(String), - OverflowingMath, InvalidChar(u128), StackFrameLimitReached, OutOfTls, @@ -124,10 +125,10 @@ pub enum EvalErrorKind<'tcx> { pub type EvalResult<'tcx, T = ()> = Result>; -impl<'tcx> Error for EvalError<'tcx> { - fn description(&self) -> &str { +impl<'tcx> EvalErrorKind<'tcx> { + pub fn description(&self) -> &str { use self::EvalErrorKind::*; - match self.kind { + match *self { MachineError(ref inner) => inner, FunctionPointerTyMismatch(..) => "tried to call a function through a function pointer of a different type", @@ -176,12 +177,8 @@ impl<'tcx> Error for EvalError<'tcx> { "tried to treat a memory pointer as a function pointer", ArrayIndexOutOfBounds(..) => "array index out of bounds", - Math(..) => - "mathematical operation failed", Intrinsic(..) => "intrinsic failed", - OverflowingMath => - "attempted to do overflowing math", NoMirFor(..) => "mir not found", InvalidChar(..) => @@ -239,6 +236,17 @@ impl<'tcx> Error for EvalError<'tcx> { "encountered constants with type errors, stopping evaluation", ReferencedConstant => "referenced constant has errors", + Overflow(mir::BinOp::Add) => "attempt to add with overflow", + Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow", + Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow", + Overflow(mir::BinOp::Div) => "attempt to divide with overflow", + Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow", + OverflowNeg => "attempt to negate with overflow", + Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow", + Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow", + Overflow(op) => bug!("{:?} cannot overflow", op), + DivisionByZero => "attempt to divide by zero", + RemainderByZero => "attempt to calculate the remainder with a divisor of zero", } } } @@ -280,8 +288,6 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "tried to reallocate memory from {} to {}", old, new), DeallocatedWrongMemoryKind(ref old, ref new) => write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new), - Math(_, ref err) => - write!(f, "{}", err.description()), Intrinsic(ref err) => write!(f, "{}", err), InvalidChar(c) => @@ -299,45 +305,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2), - _ => write!(f, "{}", self.description()), - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum ConstMathErr { - Overflow(Op), - DivisionByZero, - RemainderByZero, -} -pub use self::ConstMathErr::*; - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -} - -impl ConstMathErr { - pub fn description(&self) -> &'static str { - use self::Op::*; - match *self { - Overflow(Add) => "attempt to add with overflow", - Overflow(Sub) => "attempt to subtract with overflow", - Overflow(Mul) => "attempt to multiply with overflow", - Overflow(Div) => "attempt to divide with overflow", - Overflow(Rem) => "attempt to calculate the remainder with overflow", - Overflow(Neg) => "attempt to negate with overflow", - Overflow(Shr) => "attempt to shift right with overflow", - Overflow(Shl) => "attempt to shift left with overflow", - DivisionByZero => "attempt to divide by zero", - RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + _ => write!(f, "{}", self.kind.description()), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index fe29222e883ce..a521caf4fdadb 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -8,7 +8,7 @@ macro_rules! err { mod error; mod value; -pub use self::error::{EvalError, EvalResult, EvalErrorKind, Op, ConstMathErr}; +pub use self::error::{EvalError, EvalResult, EvalErrorKind}; pub use self::value::{PrimVal, PrimValKind, Value, Pointer}; @@ -23,7 +23,7 @@ use std::iter; use syntax::ast::Mutability; use rustc_serialize::{Encoder, Decoder, Decodable, Encodable}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Lock { NoLock, WriteLock(DynamicLifetime), @@ -31,13 +31,13 @@ pub enum Lock { ReadLock(Vec), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct DynamicLifetime { pub frame: usize, pub region: Option, // "None" indicates "until the function ends" } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum AccessKind { Read, Write, @@ -88,12 +88,12 @@ pub trait PointerArithmetic: layout::HasDataLayout { fn signed_offset<'tcx>(self, val: u64, i: i64) -> EvalResult<'tcx, u64> { let (res, over) = self.overflowing_signed_offset(val, i as i128); - if over { err!(OverflowingMath) } else { Ok(res) } + if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) } } fn offset<'tcx>(self, val: u64, i: u64) -> EvalResult<'tcx, u64> { let (res, over) = self.overflowing_offset(val, i); - if over { err!(OverflowingMath) } else { Ok(res) } + if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) } } fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3c4b9ae33519e..0b56dbda42c5e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -25,7 +25,7 @@ use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; use mir::visit::MirVisitable; -use mir::interpret::{Value, PrimVal, ConstMathErr}; +use mir::interpret::{Value, PrimVal, EvalErrorKind}; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -1211,7 +1211,7 @@ pub enum AssertMessage<'tcx> { len: Operand<'tcx>, index: Operand<'tcx> }, - Math(ConstMathErr), + Math(EvalErrorKind<'tcx>), GeneratorResumedAfterReturn, GeneratorResumedAfterPanic, } @@ -1920,9 +1920,9 @@ pub fn print_miri_value(value: Value, ty: Ty, f: &mut W) -> fmt::Resul (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"), (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"), (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) => - write!(f, "{}", Single::from_bits(bits)), + write!(f, "{}f32", Single::from_bits(bits)), (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) => - write!(f, "{}", Double::from_bits(bits)), + write!(f, "{}f64", Double::from_bits(bits)), (Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui), (Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i), (Value::ByVal(PrimVal::Bytes(n)), &TyChar) => diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 55137e2891123..92cea61bae5cf 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -149,7 +149,7 @@ pub const FAT_PTR_ADDR: usize = 0; /// - For a slice, this is the length. pub const FAT_PTR_EXTRA: usize = 1; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index f81617a3795a7..bae91d064a5a6 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -505,9 +505,7 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { DerefFunctionPointer => DerefFunctionPointer, ExecuteMemory => ExecuteMemory, ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b), - Math(sp, ref err) => Math(sp, err.clone()), Intrinsic(ref s) => Intrinsic(s.clone()), - OverflowingMath => OverflowingMath, InvalidChar(c) => InvalidChar(c), StackFrameLimitReached => StackFrameLimitReached, OutOfTls => OutOfTls, @@ -568,6 +566,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { UnimplementedTraitSelection => UnimplementedTraitSelection, TypeckError => TypeckError, ReferencedConstant => ReferencedConstant, + OverflowNeg => OverflowNeg, + Overflow(op) => Overflow(op), + DivisionByZero => DivisionByZero, + RemainderByZero => RemainderByZero, }; Some(interpret::EvalError { kind: kind, diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index a3798f3ed4c65..33c80ab22a3c4 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -20,7 +20,7 @@ use rustc::middle::const_val::ConstVal; use rustc::middle::region; use rustc::ty::{self, Ty}; use rustc::mir::*; -use rustc::mir::interpret::{Value, PrimVal, ConstMathErr, Op}; +use rustc::mir::interpret::{Value, PrimVal, EvalErrorKind}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { @@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.push_assign(block, source_info, &is_min, Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval)); - let err = ConstMathErr::Overflow(Op::Neg); + let err = EvalErrorKind::OverflowNeg; block = this.assert(block, Operand::Move(is_min), false, AssertMessage::Math(err), expr_span); } @@ -310,16 +310,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let val = result_value.clone().field(val_fld, ty); let of = result_value.field(of_fld, bool_ty); - let err = ConstMathErr::Overflow(match op { - BinOp::Add => Op::Add, - BinOp::Sub => Op::Sub, - BinOp::Mul => Op::Mul, - BinOp::Shl => Op::Shl, - BinOp::Shr => Op::Shr, - _ => { - bug!("MIR build_binary_op: {:?} is not checkable", op) - } - }); + let err = EvalErrorKind::Overflow(op); block = self.assert(block, Operand::Move(of), false, AssertMessage::Math(err), span); @@ -331,11 +322,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // and 2. there are two possible failure cases, divide-by-zero and overflow. let (zero_err, overflow_err) = if op == BinOp::Div { - (ConstMathErr::DivisionByZero, - ConstMathErr::Overflow(Op::Div)) + (EvalErrorKind::DivisionByZero, + EvalErrorKind::Overflow(op)) } else { - (ConstMathErr::RemainderByZero, - ConstMathErr::Overflow(Op::Rem)) + (EvalErrorKind::RemainderByZero, + EvalErrorKind::Overflow(op)) }; // Check for / 0 diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index f6e9994b5da3f..d055c979d1162 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -513,7 +513,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M // it emits in debug mode) is performance, but it doesn't cost us any performance in miri. // If, however, the compiler ever starts transforming unchecked intrinsics into unchecked binops, // we have to go back to just ignoring the overflow here. - return err!(OverflowingMath); + return err!(Overflow(bin_op)); } } diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 5a815e0dc67ef..6e7a37c2228df 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -269,7 +269,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { (Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)), (Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)), - (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowingMath), + (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowNeg), (Neg, _) => (-(bytes as i128)) as u128, }; diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index aa80ee7af18fc..4f0e97f6e1abe 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -160,9 +160,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { .to_u64()?; err!(ArrayIndexOutOfBounds(span, len, index)) } - Math(ref err) => { - err!(Math(terminator.source_info.span, err.clone())) - } + Math(ref err) => Err(err.clone().into()), GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => unimplemented!(), }; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 47b2f430bc70e..192ab6e17e76a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -328,7 +328,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } else { if overflow { use rustc::mir::interpret::EvalErrorKind; - let mut err = EvalErrorKind::OverflowingMath.into(); + let mut err = EvalErrorKind::Overflow(op).into(); ecx.report(&mut err, false, Some(span)); return None; } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 7c854ef04b7ca..32cb6c72d589b 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -311,10 +311,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.cx.check_overflow { - use rustc::mir::interpret::ConstMathErr::Overflow; - use rustc::mir::interpret::Op::Neg; + use rustc::mir::interpret::EvalErrorKind::OverflowNeg; - if let mir::AssertMessage::Math(Overflow(Neg)) = *msg { + if let mir::AssertMessage::Math(OverflowNeg) = *msg { const_cond = Some(expected); } } From 5f46e5cc7e9fbe433fe40d013c19d8d641e7edc0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 15:02:54 +0200 Subject: [PATCH 12/16] Update ui test output --- src/test/ui/const-eval/promoted_errors.stderr | 12 ++++++------ src/test/ui/error-codes/E0080.stderr | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr index a5db8cc908331..59dcc2bac42ee 100644 --- a/src/test/ui/const-eval/promoted_errors.stderr +++ b/src/test/ui/const-eval/promoted_errors.stderr @@ -2,7 +2,7 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 0u32 - 1); - | ^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^ attempt to subtract with overflow | = note: #[warn(const_err)] on by default @@ -10,13 +10,13 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 0u32 - 1); - | ^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^ attempt to subtract with overflow warning: constant evaluation error --> $DIR/promoted_errors.rs:17:14 | LL | let _x = 0u32 - 1; - | ^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^ attempt to subtract with overflow warning: attempt to divide by zero --> $DIR/promoted_errors.rs:19:20 @@ -28,7 +28,7 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:19:20 | LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide with overflow warning: attempt to divide by zero --> $DIR/promoted_errors.rs:22:14 @@ -40,11 +40,11 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:22:14 | LL | let _x = 1/(1-1); - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide with overflow warning: constant evaluation error --> $DIR/promoted_errors.rs:25:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^^^^^^^^^ attempt to divide with overflow diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr index 500e0e83a55f2..56c23f080cc2b 100644 --- a/src/test/ui/error-codes/E0080.stderr +++ b/src/test/ui/error-codes/E0080.stderr @@ -24,7 +24,7 @@ warning: constant evaluation error --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide with overflow error[E0080]: constant evaluation error --> $DIR/E0080.rs:14:9 From 01158eaec6fc53ac6d3655dc31fde9d55aac15e9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 27 Apr 2018 15:21:31 +0200 Subject: [PATCH 13/16] Unify MIR assert messages and const eval errors --- src/librustc/ich/impls_mir.rs | 21 ---------- src/librustc/ich/impls_ty.rs | 13 ++++--- src/librustc/mir/interpret/error.rs | 39 ++++++++++++------- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/mod.rs | 37 +++--------------- src/librustc/mir/visit.rs | 14 +++---- src/librustc/ty/structural_impls.rs | 23 ++++++++--- src/librustc_mir/borrow_check/mod.rs | 22 +++++------ .../borrow_check/nll/type_check/mod.rs | 3 +- src/librustc_mir/build/expr/as_place.rs | 3 +- src/librustc_mir/build/expr/as_rvalue.rs | 9 ++--- src/librustc_mir/interpret/terminator/mod.rs | 9 +++-- src/librustc_mir/transform/const_prop.rs | 12 +++--- src/librustc_mir/transform/generator.rs | 9 ++++- src/librustc_passes/mir_stats.rs | 13 +++++-- src/librustc_trans/mir/block.rs | 29 +++----------- 16 files changed, 111 insertions(+), 147 deletions(-) diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 437626ff5369a..33f43e53394f5 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -227,27 +227,6 @@ for mir::TerminatorKind<'gcx> { } } -impl<'a, 'gcx> HashStable> -for mir::AssertMessage<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - mir::AssertMessage::BoundsCheck { ref len, ref index } => { - len.hash_stable(hcx, hasher); - index.hash_stable(hcx, hasher); - } - mir::AssertMessage::Math(ref const_math_err) => { - const_math_err.hash_stable(hcx, hasher); - } - mir::AssertMessage::GeneratorResumedAfterReturn => (), - mir::AssertMessage::GeneratorResumedAfterPanic => (), - } - } -} - impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind }); impl<'a, 'gcx> HashStable> diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index a5447a3145afe..a40d8e0927740 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -535,8 +535,8 @@ for ::mir::interpret::EvalError<'gcx> { } } -impl<'a, 'gcx> HashStable> -for ::mir::interpret::EvalErrorKind<'gcx> { +impl<'a, 'gcx, O: HashStable>> HashStable> +for ::mir::interpret::EvalErrorKind<'gcx, O> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -578,6 +578,8 @@ for ::mir::interpret::EvalErrorKind<'gcx> { OverflowNeg | RemainderByZero | DivisionByZero | + GeneratorResumedAfterReturn | + GeneratorResumedAfterPanic | ReferencedConstant => {} MachineError(ref err) => err.hash_stable(hcx, hasher), FunctionPointerTyMismatch(a, b) => { @@ -597,10 +599,9 @@ for ::mir::interpret::EvalErrorKind<'gcx> { }, InvalidBoolOp(bop) => bop.hash_stable(hcx, hasher), Unimplemented(ref s) => s.hash_stable(hcx, hasher), - ArrayIndexOutOfBounds(sp, a, b) => { - sp.hash_stable(hcx, hasher); - a.hash_stable(hcx, hasher); - b.hash_stable(hcx, hasher) + BoundsCheck { ref len, ref index } => { + len.hash_stable(hcx, hasher); + index.hash_stable(hcx, hasher) }, Intrinsic(ref s) => s.hash_stable(hcx, hasher), InvalidChar(c) => c.hash_stable(hcx, hasher), diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 022b82841bcc2..1e1d50c3fc036 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -7,17 +7,16 @@ use super::{ MemoryPointer, Lock, AccessKind }; -use syntax::codemap::Span; use backtrace::Backtrace; #[derive(Debug, Clone)] pub struct EvalError<'tcx> { - pub kind: EvalErrorKind<'tcx>, + pub kind: EvalErrorKind<'tcx, u64>, pub backtrace: Option, } -impl<'tcx> From> for EvalError<'tcx> { - fn from(kind: EvalErrorKind<'tcx>) -> Self { +impl<'tcx> From> for EvalError<'tcx> { + fn from(kind: EvalErrorKind<'tcx, u64>) -> Self { let backtrace = match env::var("MIRI_BACKTRACE") { Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()), _ => None @@ -29,8 +28,10 @@ impl<'tcx> From> for EvalError<'tcx> { } } -#[derive(Debug, Clone, RustcEncodable, RustcDecodable)] -pub enum EvalErrorKind<'tcx> { +pub type AssertMessage<'tcx> = EvalErrorKind<'tcx, mir::Operand<'tcx>>; + +#[derive(Clone, RustcEncodable, RustcDecodable)] +pub enum EvalErrorKind<'tcx, O> { /// This variant is used by machines to signal their own errors that do not /// match an existing variant MachineError(String), @@ -58,7 +59,7 @@ pub enum EvalErrorKind<'tcx> { Unimplemented(String), DerefFunctionPointer, ExecuteMemory, - ArrayIndexOutOfBounds(Span, u64, u64), + BoundsCheck { len: O, index: O }, Overflow(mir::BinOp), OverflowNeg, DivisionByZero, @@ -121,11 +122,13 @@ pub enum EvalErrorKind<'tcx> { /// Cannot compute this constant because it depends on another one /// which already produced an error ReferencedConstant, + GeneratorResumedAfterReturn, + GeneratorResumedAfterPanic, } pub type EvalResult<'tcx, T = ()> = Result>; -impl<'tcx> EvalErrorKind<'tcx> { +impl<'tcx, O> EvalErrorKind<'tcx, O> { pub fn description(&self) -> &str { use self::EvalErrorKind::*; match *self { @@ -175,7 +178,7 @@ impl<'tcx> EvalErrorKind<'tcx> { "tried to dereference a function pointer", ExecuteMemory => "tried to treat a memory pointer as a function pointer", - ArrayIndexOutOfBounds(..) => + BoundsCheck{..} => "array index out of bounds", Intrinsic(..) => "intrinsic failed", @@ -228,7 +231,7 @@ impl<'tcx> EvalErrorKind<'tcx> { "the evaluated program panicked", ReadFromReturnPointer => "tried to read from the return pointer", - EvalErrorKind::PathNotFound(_) => + PathNotFound(_) => "a path could not be resolved, maybe the crate is not loaded", UnimplementedTraitSelection => "there were unresolved type arguments during trait selection", @@ -247,14 +250,22 @@ impl<'tcx> EvalErrorKind<'tcx> { Overflow(op) => bug!("{:?} cannot overflow", op), DivisionByZero => "attempt to divide by zero", RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + GeneratorResumedAfterReturn => "generator resumed after completion", + GeneratorResumedAfterPanic => "generator resumed after panicking", } } } impl<'tcx> fmt::Display for EvalError<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.kind) + } +} + +impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::EvalErrorKind::*; - match self.kind { + match *self { PointerOutOfBounds { ptr, access, allocation_size } => { write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}", if access { "memory access" } else { "pointer computed" }, @@ -282,8 +293,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { NoMirFor(ref func) => write!(f, "no mir for `{}`", func), FunctionPointerTyMismatch(sig, got) => write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got), - ArrayIndexOutOfBounds(span, len, index) => - write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span), + BoundsCheck { ref len, ref index } => + write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index), ReallocatedWrongMemoryKind(ref old, ref new) => write!(f, "tried to reallocate memory from {} to {}", old, new), DeallocatedWrongMemoryKind(ref old, ref new) => @@ -305,7 +316,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2), - _ => write!(f, "{}", self.kind.description()), + _ => write!(f, "{}", self.description()), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index a521caf4fdadb..546c7a920d538 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -8,7 +8,7 @@ macro_rules! err { mod error; mod value; -pub use self::error::{EvalError, EvalResult, EvalErrorKind}; +pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage}; pub use self::value::{PrimVal, PrimValKind, Value, Pointer}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0b56dbda42c5e..c62fe0372df41 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -45,6 +45,8 @@ use syntax_pos::{Span, DUMMY_SP}; use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; +pub use mir::interpret::AssertMessage; + mod cache; pub mod tcx; pub mod visit; @@ -1132,23 +1134,7 @@ impl<'tcx> TerminatorKind<'tcx> { write!(fmt, "!")?; } write!(fmt, "{:?}, ", cond)?; - - match *msg { - AssertMessage::BoundsCheck { ref len, ref index } => { - write!(fmt, "{:?}, {:?}, {:?}", - "index out of bounds: the len is {} but the index is {}", - len, index)?; - } - AssertMessage::Math(ref err) => { - write!(fmt, "{:?}", err.description())?; - } - AssertMessage::GeneratorResumedAfterReturn => { - write!(fmt, "{:?}", "generator resumed after completion")?; - } - AssertMessage::GeneratorResumedAfterPanic => { - write!(fmt, "{:?}", "generator resumed after panicking")?; - } - } + write!(fmt, "{:?}", msg)?; write!(fmt, ")") }, @@ -1205,17 +1191,6 @@ impl<'tcx> TerminatorKind<'tcx> { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub enum AssertMessage<'tcx> { - BoundsCheck { - len: Operand<'tcx>, - index: Operand<'tcx> - }, - Math(EvalErrorKind<'tcx>), - GeneratorResumedAfterReturn, - GeneratorResumedAfterPanic, -} - /////////////////////////////////////////////////////////////////////////// // Statements @@ -2281,8 +2256,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } }, Assert { ref cond, expected, ref msg, target, cleanup } => { - let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg { - AssertMessage::BoundsCheck { + let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { + EvalErrorKind::BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder), } @@ -2331,7 +2306,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { }, Assert { ref cond, ref msg, .. } => { if cond.visit_with(visitor) { - if let AssertMessage::BoundsCheck { ref len, ref index } = *msg { + if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { len.visit_with(visitor) || index.visit_with(visitor) } else { false diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index a3fdb6f73abb0..59b6f3697541a 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -511,17 +511,13 @@ macro_rules! make_mir_visitor { fn super_assert_message(&mut self, msg: & $($mutability)* AssertMessage<'tcx>, location: Location) { - match *msg { - AssertMessage::BoundsCheck { + use mir::interpret::EvalErrorKind::*; + if let BoundsCheck { ref $($mutability)* len, ref $($mutability)* index - } => { - self.visit_operand(len, location); - self.visit_operand(index, location); - } - AssertMessage::Math(_) => {}, - AssertMessage::GeneratorResumedAfterReturn => {}, - AssertMessage::GeneratorResumedAfterPanic => {}, + } = *msg { + self.visit_operand(len, location); + self.visit_operand(index, location); } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index bae91d064a5a6..d4ed6c60e0efa 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -473,9 +473,19 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> { impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { type Lifted = interpret::EvalError<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + Some(interpret::EvalError { + kind: tcx.lift(&self.kind)?, + backtrace: self.backtrace.clone(), + }) + } +} + +impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { + type Lifted = interpret::EvalErrorKind<'tcx, >::Lifted>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { use ::mir::interpret::EvalErrorKind::*; - let kind = match self.kind { + Some(match *self { MachineError(ref err) => MachineError(err.clone()), FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch( tcx.lift(&a)?, @@ -504,7 +514,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { Unimplemented(ref s) => Unimplemented(s.clone()), DerefFunctionPointer => DerefFunctionPointer, ExecuteMemory => ExecuteMemory, - ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b), + BoundsCheck { ref len, ref index } => BoundsCheck { + len: tcx.lift(len)?, + index: tcx.lift(index)?, + }, Intrinsic(ref s) => Intrinsic(s.clone()), InvalidChar(c) => InvalidChar(c), StackFrameLimitReached => StackFrameLimitReached, @@ -570,10 +583,8 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { Overflow(op) => Overflow(op), DivisionByZero => DivisionByZero, RemainderByZero => RemainderByZero, - }; - Some(interpret::EvalError { - kind: kind, - backtrace: self.backtrace.clone(), + GeneratorResumedAfterReturn => GeneratorResumedAfterReturn, + GeneratorResumedAfterPanic => GeneratorResumedAfterPanic, }) } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3145be7df851e..7e1c20dff6a73 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -18,7 +18,7 @@ use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::maps::Providers; use rustc::lint::builtin::UNUSED_MUT; -use rustc::mir::{AssertMessage, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; +use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand}; use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -586,18 +586,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx cleanup: _, } => { self.consume_operand(ContextKind::Assert.new(loc), (cond, span), flow_state); - match *msg { - AssertMessage::BoundsCheck { ref len, ref index } => { - self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state); - self.consume_operand( - ContextKind::Assert.new(loc), - (index, span), - flow_state, - ); - } - AssertMessage::Math(_ /*const_math_err*/) => {} - AssertMessage::GeneratorResumedAfterReturn => {} - AssertMessage::GeneratorResumedAfterPanic => {} + use rustc::mir::interpret::EvalErrorKind::BoundsCheck; + if let BoundsCheck { ref len, ref index } = *msg { + self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state); + self.consume_operand( + ContextKind::Assert.new(loc), + (index, span), + flow_state, + ); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a811b2c147e98..a21b9196badb5 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -22,6 +22,7 @@ use rustc::infer::region_constraints::{GenericKind, RegionConstraintData}; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc::mir::*; use rustc::traits::query::NoSolution; use rustc::traits::{self, Normalized, TraitEngine}; @@ -928,7 +929,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty); } - if let AssertMessage::BoundsCheck { ref len, ref index } = *msg { + if let BoundsCheck { ref len, ref index } = *msg { if len.ty(mir, tcx) != tcx.types.usize { span_mirbug!(self, len, "bounds-check length non-usize {:?}", len) } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 9e21790851167..19ec13324d6b4 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -14,6 +14,7 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::Category; use hair::*; use rustc::mir::*; +use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc_data_structures::indexed_vec::Idx; @@ -73,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Operand::Copy(Place::Local(idx)), Operand::Copy(len.clone()))); - let msg = AssertMessage::BoundsCheck { + let msg = BoundsCheck { len: Operand::Move(len), index: Operand::Copy(Place::Local(idx)) }; diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 33c80ab22a3c4..9e96fdf821417 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -85,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.push_assign(block, source_info, &is_min, Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval)); - let err = EvalErrorKind::OverflowNeg; block = this.assert(block, Operand::Move(is_min), false, - AssertMessage::Math(err), expr_span); + EvalErrorKind::OverflowNeg, expr_span); } block.and(Rvalue::UnaryOp(op, arg)) } @@ -313,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let err = EvalErrorKind::Overflow(op); block = self.assert(block, Operand::Move(of), false, - AssertMessage::Math(err), span); + err, span); block.and(Rvalue::Use(Operand::Move(val))) } else { @@ -336,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero)); block = self.assert(block, Operand::Move(is_zero), false, - AssertMessage::Math(zero_err), span); + zero_err, span); // We only need to check for the overflow in one case: // MIN / -1, and only for signed values. @@ -361,7 +360,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min)); block = self.assert(block, Operand::Move(of), false, - AssertMessage::Math(overflow_err), span); + overflow_err, span); } } diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index 4f0e97f6e1abe..b630725b0d2d1 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -148,21 +148,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { if expected == cond_val { self.goto_block(target); } else { - use rustc::mir::AssertMessage::*; + use rustc::mir::interpret::EvalErrorKind::*; return match *msg { BoundsCheck { ref len, ref index } => { - let span = terminator.source_info.span; let len = self.eval_operand_to_primval(len) .expect("can't eval len") .to_u64()?; let index = self.eval_operand_to_primval(index) .expect("can't eval index") .to_u64()?; - err!(ArrayIndexOutOfBounds(span, len, index)) + err!(BoundsCheck { len, index }) } - Math(ref err) => Err(err.clone().into()), + Overflow(op) => Err(Overflow(op).into()), + OverflowNeg => Err(OverflowNeg.into()), GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => unimplemented!(), + _ => bug!(), }; } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 192ab6e17e76a..e1db216b6bbbc 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -478,12 +478,12 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { .hir .as_local_node_id(self.source.def_id) .expect("some part of a failing const eval must be local"); - use rustc::mir::AssertMessage::*; + use rustc::mir::interpret::EvalErrorKind::*; let msg = match msg { - // Need proper const propagator for these - GeneratorResumedAfterReturn | - GeneratorResumedAfterPanic => return, - Math(ref err) => err.description().to_owned(), + Overflow(_) | + OverflowNeg | + DivisionByZero | + RemainderByZero => msg.description().to_owned(), BoundsCheck { ref len, ref index } => { let len = self.eval_operand(len).expect("len must be const"); let len = match len.0 { @@ -504,6 +504,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { index, ) }, + // Need proper const propagator for these + _ => return, }; self.tcx.lint_node( ::rustc::lint::builtin::CONST_ERR, diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0ff7356943388..36735586e8117 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -738,12 +738,17 @@ fn create_generator_resume_function<'a, 'tcx>( let mut cases = create_cases(mir, &transform, |point| Some(point.resume)); + use rustc::mir::interpret::EvalErrorKind::{ + GeneratorResumedAfterPanic, + GeneratorResumedAfterReturn, + }; + // Jump to the entry point on the 0 state cases.insert(0, (0, BasicBlock::new(0))); // Panic when resumed on the returned (1) state - cases.insert(1, (1, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterReturn))); + cases.insert(1, (1, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn))); // Panic when resumed on the poisoned (2) state - cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic))); + cases.insert(2, (2, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic))); insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable); diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index a4e056c6b589e..45c6e89321d04 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -18,6 +18,7 @@ use rustc::mir::{Place, PlaceElem, PlaceProjection}; use rustc::mir::{Mir, Operand, ProjectionElem}; use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData}; +use rustc::mir::interpret::EvalErrorKind; use rustc::mir::visit as mir_visit; use rustc::ty::{self, ClosureSubsts, TyCtxt}; use rustc::util::nodemap::{FxHashMap}; @@ -133,14 +134,18 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { location: Location) { self.record("AssertMessage", msg); self.record(match *msg { - AssertMessage::BoundsCheck { .. } => "AssertMessage::BoundsCheck", - AssertMessage::Math(..) => "AssertMessage::Math", - AssertMessage::GeneratorResumedAfterReturn => { + EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck", + EvalErrorKind::Overflow(..) => "AssertMessage::Overflow", + EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg", + EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero", + EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero", + EvalErrorKind::GeneratorResumedAfterReturn => { "AssertMessage::GeneratorResumedAfterReturn" } - AssertMessage::GeneratorResumedAfterPanic => { + EvalErrorKind::GeneratorResumedAfterPanic => { "AssertMessage::GeneratorResumedAfterPanic" } + _ => bug!(), }, msg); self.super_assert_message(msg, location); } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 32cb6c72d589b..b666c2b211525 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -13,6 +13,7 @@ use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf}; use rustc::mir; +use rustc::mir::interpret::EvalErrorKind; use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode}; use base; use callee; @@ -311,9 +312,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.cx.check_overflow { - use rustc::mir::interpret::EvalErrorKind::OverflowNeg; - - if let mir::AssertMessage::Math(OverflowNeg) = *msg { + if let mir::interpret::EvalErrorKind::OverflowNeg = *msg { const_cond = Some(expected); } } @@ -353,7 +352,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // Put together the arguments to the panic entry point. let (lang_item, args) = match *msg { - mir::AssertMessage::BoundsCheck { ref len, ref index } => { + EvalErrorKind::BoundsCheck { ref len, ref index } => { let len = self.trans_operand(&mut bx, len).immediate(); let index = self.trans_operand(&mut bx, index).immediate(); @@ -365,26 +364,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { (lang_items::PanicBoundsCheckFnLangItem, vec![file_line_col, index, len]) } - mir::AssertMessage::Math(ref err) => { - let msg_str = Symbol::intern(err.description()).as_str(); - let msg_str = C_str_slice(bx.cx, msg_str); - let msg_file_line_col = C_struct(bx.cx, - &[msg_str, filename, line, col], - false); - let msg_file_line_col = consts::addr_of(bx.cx, - msg_file_line_col, - align, - "panic_loc"); - (lang_items::PanicFnLangItem, - vec![msg_file_line_col]) - } - mir::AssertMessage::GeneratorResumedAfterReturn | - mir::AssertMessage::GeneratorResumedAfterPanic => { - let str = if let mir::AssertMessage::GeneratorResumedAfterReturn = *msg { - "generator resumed after completion" - } else { - "generator resumed after panicking" - }; + _ => { + let str = msg.description(); let msg_str = Symbol::intern(str).as_str(); let msg_str = C_str_slice(bx.cx, msg_str); let msg_file_line_col = C_struct(bx.cx, From 1f3cb926a24897d6524920bb38618b4b6ee17aa7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 27 Apr 2018 15:21:42 +0200 Subject: [PATCH 14/16] Update Cargo.lock --- src/Cargo.lock | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index a6f78a7e6b442..940ca1aace053 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1728,7 +1728,6 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_apfloat 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", @@ -1872,15 +1871,6 @@ dependencies = [ "syntax_pos 0.0.0", ] -[[package]] -name = "rustc_const_math" -version = "0.0.0" -dependencies = [ - "rustc_apfloat 0.0.0", - "serialize 0.0.0", - "syntax 0.0.0", -] - [[package]] name = "rustc_cratesio_shim" version = "0.0.0" @@ -2026,7 +2016,6 @@ dependencies = [ "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_apfloat 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", @@ -2053,7 +2042,6 @@ version = "0.0.0" dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_mir 0.0.0", @@ -2154,7 +2142,6 @@ dependencies = [ "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_incremental 0.0.0", @@ -2205,7 +2192,6 @@ dependencies = [ "fmt_macros 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_platform_intrinsics 0.0.0", From f66367daccd2352d14730e472e8dfdef244aec63 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 28 Apr 2018 13:35:35 +0200 Subject: [PATCH 15/16] Improve div by zero const eval errors --- src/librustc/mir/mod.rs | 2 +- src/librustc_mir/interpret/operator.rs | 6 ++++-- src/librustc_mir/interpret/terminator/mod.rs | 2 ++ src/test/ui/const-eval/index_out_of_bound.stderr | 2 +- src/test/ui/const-eval/promoted_errors.stderr | 6 +++--- src/test/ui/error-codes/E0080.rs | 1 - src/test/ui/error-codes/E0080.stderr | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c62fe0372df41..624f8ed789cd6 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1134,7 +1134,7 @@ impl<'tcx> TerminatorKind<'tcx> { write!(fmt, "!")?; } write!(fmt, "{:?}, ", cond)?; - write!(fmt, "{:?}", msg)?; + write!(fmt, "\"{:?}\"", msg)?; write!(fmt, ")") }, diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 6e7a37c2228df..ef6deab047750 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -140,7 +140,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { return Ok((PrimVal::from_bool(op(&l, &r)), false)); } let op: Option (i128, bool)> = match bin_op { - Rem | Div if r == 0 => return Ok((PrimVal::Bytes(l), true)), + Div if r == 0 => return err!(DivisionByZero), + Rem if r == 0 => return err!(RemainderByZero), Div => Some(i128::overflowing_div), Rem => Some(i128::overflowing_rem), Add => Some(i128::overflowing_add), @@ -221,7 +222,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Add => u128::overflowing_add, Sub => u128::overflowing_sub, Mul => u128::overflowing_mul, - Rem | Div if r == 0 => return Ok((PrimVal::Bytes(l), true)), + Div if r == 0 => return err!(DivisionByZero), + Rem if r == 0 => return err!(RemainderByZero), Div => u128::overflowing_div, Rem => u128::overflowing_rem, _ => bug!(), diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index b630725b0d2d1..0e0d91f472472 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -161,6 +161,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } Overflow(op) => Err(Overflow(op).into()), OverflowNeg => Err(OverflowNeg.into()), + DivisionByZero => Err(DivisionByZero.into()), + RemainderByZero => Err(RemainderByZero.into()), GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => unimplemented!(), _ => bug!(), diff --git a/src/test/ui/const-eval/index_out_of_bound.stderr b/src/test/ui/const-eval/index_out_of_bound.stderr index 793e0a7ace8d8..d16231c72b91a 100644 --- a/src/test/ui/const-eval/index_out_of_bound.stderr +++ b/src/test/ui/const-eval/index_out_of_bound.stderr @@ -2,7 +2,7 @@ error[E0080]: constant evaluation error --> $DIR/index_out_of_bound.rs:11:19 | LL | static FOO: i32 = [][0]; - | ^^^^^ index out of bounds: the len is 0 but the index is 0 at $DIR/index_out_of_bound.rs:11:19: 11:24 + | ^^^^^ index out of bounds: the len is 0 but the index is 0 error: aborting due to previous error diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr index 59dcc2bac42ee..7761f192fdb70 100644 --- a/src/test/ui/const-eval/promoted_errors.stderr +++ b/src/test/ui/const-eval/promoted_errors.stderr @@ -28,7 +28,7 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:19:20 | LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide with overflow + | ^^^^^^^ attempt to divide by zero warning: attempt to divide by zero --> $DIR/promoted_errors.rs:22:14 @@ -40,11 +40,11 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:22:14 | LL | let _x = 1/(1-1); - | ^^^^^^^ attempt to divide with overflow + | ^^^^^^^ attempt to divide by zero warning: constant evaluation error --> $DIR/promoted_errors.rs:25:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide with overflow + | ^^^^^^^^^^^^^^^^ attempt to divide by zero diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs index c8e425711284e..7f3e6eaad9b17 100644 --- a/src/test/ui/error-codes/E0080.rs +++ b/src/test/ui/error-codes/E0080.rs @@ -15,7 +15,6 @@ enum Enum { //~| const_err //~| const_err //~| const_err - //~| divide by zero } fn main() { diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr index 56c23f080cc2b..5e401bd6c79da 100644 --- a/src/test/ui/error-codes/E0080.stderr +++ b/src/test/ui/error-codes/E0080.stderr @@ -24,7 +24,7 @@ warning: constant evaluation error --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 - | ^^^^^^^ attempt to divide with overflow + | ^^^^^^^ attempt to divide by zero error[E0080]: constant evaluation error --> $DIR/E0080.rs:14:9 From 487f7bc016aeca615ada10fce5bcd7190702bda6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 1 May 2018 12:26:58 +0200 Subject: [PATCH 16/16] Merge adjacent write! invocations --- src/librustc/mir/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 624f8ed789cd6..3bbec3915dd5b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1133,10 +1133,7 @@ impl<'tcx> TerminatorKind<'tcx> { if !expected { write!(fmt, "!")?; } - write!(fmt, "{:?}, ", cond)?; - write!(fmt, "\"{:?}\"", msg)?; - - write!(fmt, ")") + write!(fmt, "{:?}, \"{:?}\")", cond, msg) }, FalseEdges { .. } => write!(fmt, "falseEdges"), FalseUnwind { .. } => write!(fmt, "falseUnwind"),