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", 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 5f3ff461c0c7e..0000000000000 --- a/src/librustc/ich/impls_const_math.rs +++ /dev/null @@ -1,44 +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!(struct ::rustc_const_math::ConstFloat { - ty, - bits -}); - -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 { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, - BitAnd, - BitOr, - BitXor -}); 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 5ab8d6eb7b3e0..a40d8e0927740 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); } @@ -528,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, O: HashStable>> HashStable> +for ::mir::interpret::EvalErrorKind<'gcx, O> { 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 | @@ -568,8 +575,12 @@ for ::mir::interpret::EvalError<'gcx> { TypeckError | DerefFunctionPointer | ExecuteMemory | - ReferencedConstant | - OverflowingMath => {} + OverflowNeg | + RemainderByZero | + DivisionByZero | + GeneratorResumedAfterReturn | + GeneratorResumedAfterPanic | + ReferencedConstant => {} MachineError(ref err) => err.hash_stable(hcx, hasher), FunctionPointerTyMismatch(a, b) => { a.hash_stable(hcx, hasher); @@ -588,14 +599,9 @@ for ::mir::interpret::EvalError<'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) - }, - Math(sp, ref err) => { - sp.hash_stable(hcx, hasher); - err.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), @@ -668,6 +674,7 @@ 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), } } } 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 9dc9fb1144efa..879d38c489443 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/middle/const_val.rs b/src/librustc/middle/const_val.rs index 19a7576b7ceac..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,15 +74,6 @@ pub struct FrameInfo { pub location: String, } -impl<'tcx> From for ErrKind<'tcx> { - fn from(err: ConstMathErr) -> ErrKind<'tcx> { - match err { - ConstMathErr::UnsignedNegation => ErrKind::TypeckError, - _ => ErrKind::Math(err) - } - } -} - #[derive(Clone, Debug)] pub enum ConstEvalErrDescription<'a, 'tcx: 'a> { Simple(Cow<'a, str>), @@ -122,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/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index b919f4d15a840..1e1d50c3fc036 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; @@ -8,18 +7,16 @@ use super::{ MemoryPointer, Lock, AccessKind }; -use rustc_const_math::ConstMathErr; -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 @@ -31,8 +28,10 @@ impl<'tcx> From> for EvalError<'tcx> { } } -#[derive(Debug, Clone)] -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), @@ -60,10 +59,12 @@ pub enum EvalErrorKind<'tcx> { Unimplemented(String), DerefFunctionPointer, ExecuteMemory, - ArrayIndexOutOfBounds(Span, u64, u64), - Math(Span, ConstMathErr), + BoundsCheck { len: O, index: O }, + Overflow(mir::BinOp), + OverflowNeg, + DivisionByZero, + RemainderByZero, Intrinsic(String), - OverflowingMath, InvalidChar(u128), StackFrameLimitReached, OutOfTls, @@ -121,14 +122,16 @@ 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> Error for EvalError<'tcx> { - fn description(&self) -> &str { +impl<'tcx, O> EvalErrorKind<'tcx, O> { + 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", @@ -175,14 +178,10 @@ impl<'tcx> Error for EvalError<'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", - Math(..) => - "mathematical operation failed", Intrinsic(..) => "intrinsic failed", - OverflowingMath => - "attempted to do overflowing math", NoMirFor(..) => "mir not found", InvalidChar(..) => @@ -232,7 +231,7 @@ impl<'tcx> Error for EvalError<'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", @@ -240,14 +239,33 @@ 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", + 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" }, @@ -275,14 +293,12 @@ 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) => 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) => diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index c9eed0e4a2885..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}; @@ -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 c26b3014e53dd..3bbec3915dd5b 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, EvalErrorKind}; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -43,6 +42,10 @@ 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; + +pub use mir::interpret::AssertMessage; mod cache; pub mod tcx; @@ -1130,26 +1133,7 @@ impl<'tcx> TerminatorKind<'tcx> { if !expected { 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, ")") + write!(fmt, "{:?}, \"{:?}\")", cond, msg) }, FalseEdges { .. } => write!(fmt, "falseEdges"), FalseUnwind { .. } => write!(fmt, "falseUnwind"), @@ -1204,17 +1188,6 @@ impl<'tcx> TerminatorKind<'tcx> { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub enum AssertMessage<'tcx> { - BoundsCheck { - len: Operand<'tcx>, - index: Operand<'tcx> - }, - Math(ConstMathErr), - GeneratorResumedAfterReturn, - GeneratorResumedAfterPanic, -} - /////////////////////////////////////////////////////////////////////////// // Statements @@ -1915,12 +1888,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, "{}f32", Single::from_bits(bits)), + (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) => + 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) => @@ -2279,8 +2253,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), } @@ -2329,7 +2303,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/layout.rs b/src/librustc/ty/layout.rs index 47b52cacd56bd..53dde3e6903f9 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -148,7 +148,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 9b20fce667318..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,10 +514,11 @@ 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), - Math(sp, ref err) => Math(sp, err.clone()), + BoundsCheck { ref len, ref index } => BoundsCheck { + len: tcx.lift(len)?, + index: tcx.lift(index)?, + }, Intrinsic(ref s) => Intrinsic(s.clone()), - OverflowingMath => OverflowingMath, InvalidChar(c) => InvalidChar(c), StackFrameLimitReached => StackFrameLimitReached, OutOfTls => OutOfTls, @@ -568,10 +579,12 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { UnimplementedTraitSelection => UnimplementedTraitSelection, TypeckError => TypeckError, ReferencedConstant => ReferencedConstant, - }; - Some(interpret::EvalError { - kind: kind, - backtrace: self.backtrace.clone(), + OverflowNeg => OverflowNeg, + Overflow(op) => Overflow(op), + DivisionByZero => DivisionByZero, + RemainderByZero => RemainderByZero, + GeneratorResumedAfterReturn => GeneratorResumedAfterReturn, + GeneratorResumedAfterPanic => GeneratorResumedAfterPanic, }) } } @@ -585,7 +598,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) 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. 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 bd0a332436e64..0000000000000 --- a/src/librustc_const_math/err.rs +++ /dev/null @@ -1,87 +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 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::*; - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, - BitAnd, - BitOr, - BitXor, -} - -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", - 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", - 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", - 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", - } - } -} diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs deleted file mode 100644 index 9d820ea8cbed2..0000000000000 --- a/src/librustc_const_math/float.rs +++ /dev/null @@ -1,213 +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}; - -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 -// 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 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 - pub fn try_cmp(self, rhs: Self) -> Result { - 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)) - } - - (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)) - } - - _ => Err(CmpBetweenUnequalTypes), - } - } - - 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 = Result; - fn $func(self, rhs: Self) -> Result { - 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 Err(UnequalTypes(Op::$op)), - }; - Ok(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 deleted file mode 100644 index 499c330be1da8..0000000000000 --- a/src/librustc_const_math/lib.rs +++ /dev/null @@ -1,31 +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 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/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/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 b7f402f61a9c1..9e96fdf821417 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, EvalErrorKind}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { @@ -86,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 = ConstMathErr::Overflow(Op::Neg); block = this.assert(block, Operand::Move(is_min), false, - AssertMessage::Math(err), expr_span); + EvalErrorKind::OverflowNeg, expr_span); } block.and(Rvalue::UnaryOp(op, arg)) } @@ -311,19 +309,10 @@ 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); + err, span); block.and(Rvalue::Use(Operand::Move(val))) } else { @@ -332,11 +321,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 @@ -346,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. @@ -371,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/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index e6aa2d3abb7e0..5890ea5c9d0c6 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,12 +170,11 @@ 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(|_| { + 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 - tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); + self.tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); }) }; @@ -213,26 +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(); - let mut f = parse_float(&n, fty); - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(n, fty) } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => 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) } 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 c2da8c11d87e9..619b4596b4227 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -28,13 +28,13 @@ 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; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; +use syntax_pos::symbol::Symbol; #[derive(Clone, Debug)] pub enum PatternError { @@ -1053,24 +1053,22 @@ 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, - }; - // FIXME(oli-obk): report cmp errors? - l.try_cmp(r).ok() + 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(_) => { let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt"); @@ -1148,26 +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(); - 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)? } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => 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)? } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), @@ -1175,7 +1161,36 @@ 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: Symbol, + fty: ast::FloatTy, + neg: bool, +) -> Result { + let num = num.as_str(); + use rustc_apfloat::ieee::{Single, Double}; + use rustc_apfloat::Float; + let bits = match fty { + ast::FloatTy::F32 => { + 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 => { + 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() + } + }; + + 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/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index c8cebf8328d59..e1b358a5eb779 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 dfc0c4a824a84..ef6deab047750 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.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), - 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), @@ -164,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), @@ -199,7 +176,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 @@ -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!(), @@ -269,7 +271,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..0e0d91f472472 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -148,23 +148,24 @@ 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)) - } - Math(ref err) => { - err!(Math(terminator.source_info.span, err.clone())) + err!(BoundsCheck { len, index }) } + 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/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a6dc4c74f3634..95cf3b8ddc6ce 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_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 47b2f430bc70e..e1db216b6bbbc 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; } @@ -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/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_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/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 9259fef279f1a..7a152d6ded4c5 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..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,10 +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_const_math::ConstMathErr::Overflow; - use rustc_const_math::Op::Neg; - - if let mir::AssertMessage::Math(Overflow(Neg)) = *msg { + if let mir::interpret::EvalErrorKind::OverflowNeg = *msg { const_cond = Some(expected); } } @@ -354,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(); @@ -366,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, diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 4fa54dc276d20..0cd823391b9b6 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); 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; 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 a5db8cc908331..7761f192fdb70 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 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); - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide by zero warning: constant evaluation error --> $DIR/promoted_errors.rs:25:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^^^^^^^^^ 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 500e0e83a55f2..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 - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide by zero error[E0080]: constant evaluation error --> $DIR/E0080.rs:14:9