Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/librustc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
44 changes: 0 additions & 44 deletions src/librustc/ich/impls_const_math.rs

This file was deleted.

21 changes: 0 additions & 21 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
@@ -227,27 +227,6 @@ for mir::TerminatorKind<'gcx> {
}
}

impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
for mir::AssertMessage<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
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<StableHashingContext<'a>>
37 changes: 22 additions & 15 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
@@ -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<StableHashingContext<'a>>
for ::mir::interpret::EvalError<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
self.kind.hash_stable(hcx, hasher)
}
}

impl<'a, 'gcx, O: HashStable<StableHashingContext<'a>>> HashStable<StableHashingContext<'a>>
for ::mir::interpret::EvalErrorKind<'gcx, O> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
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),
}
}
}
1 change: 0 additions & 1 deletion src/librustc/ich/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
1 change: 0 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
12 changes: 0 additions & 12 deletions src/librustc/middle/const_val.rs
Original file line number Diff line number Diff line change
@@ -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<ConstMathErr> 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"),
66 changes: 41 additions & 25 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
@@ -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<Backtrace>,
}

impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx>) -> Self {
impl<'tcx> From<EvalErrorKind<'tcx, u64>> 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<EvalErrorKind<'tcx>> 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<T, EvalError<'tcx>>;

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,22 +231,41 @@ 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",
TypeckError =>
"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) =>
12 changes: 6 additions & 6 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
@@ -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,21 +23,21 @@ 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),
/// This should never be empty -- that would be a read lock held and nobody there to release it...
ReadLock(Vec<DynamicLifetime>),
}

#[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<region::Scope>, // "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 {
52 changes: 13 additions & 39 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -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> {
Copy link
Member

@eddyb eddyb Apr 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, can you put Box around the use of AssertMessage in TerminatorKind::Assert? Just to avoid the memory usage blowup. Nevermind, terminators are once per block, what am I even thinking.

BoundsCheck {
len: Operand<'tcx>,
index: Operand<'tcx>
},
Math(ConstMathErr),
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
}

///////////////////////////////////////////////////////////////////////////
// Statements

@@ -1915,12 +1888,13 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {

pub fn print_miri_value<W: Write>(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
14 changes: 5 additions & 9 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}

2 changes: 1 addition & 1 deletion src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
@@ -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>)
30 changes: 21 additions & 9 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
@@ -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<Self::Lifted> {
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, <O as Lift<'tcx>>::Lifted>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
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)
2 changes: 1 addition & 1 deletion src/librustc_apfloat/ppc.rs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ use std::ops::Neg;
pub struct DoubleFloat<F>(F, F);
pub type DoubleDouble = DoubleFloat<ieee::Double>;

// These are legacy semantics for the Fallback, inaccrurate implementation of
// These are legacy semantics for the Fallback, inaccurate implementation of
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it was meant to be ironic... 😏

// 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.
14 changes: 0 additions & 14 deletions src/librustc_const_math/Cargo.toml

This file was deleted.

87 changes: 0 additions & 87 deletions src/librustc_const_math/err.rs

This file was deleted.

213 changes: 0 additions & 213 deletions src/librustc_const_math/float.rs

This file was deleted.

31 changes: 0 additions & 31 deletions src/librustc_const_math/lib.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/librustc_mir/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
22 changes: 9 additions & 13 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
);
}
}

3 changes: 2 additions & 1 deletion src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -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)
}
3 changes: 2 additions & 1 deletion src/librustc_mir/build/expr/as_place.rs
Original file line number Diff line number Diff line change
@@ -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))
};
31 changes: 10 additions & 21 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}

25 changes: 6 additions & 19 deletions src/librustc_mir/hair/cx/mod.rs
Original file line number Diff line number Diff line change
@@ -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)),
75 changes: 45 additions & 30 deletions src/librustc_mir/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
@@ -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<Ordering> {
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,34 +1146,51 @@ 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)),
};
Ok(ConstVal::Value(lit))
}

fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
-> Result<ConstFloat, ()> {
ConstFloat::from_str(num, fty).map_err(|_| ())
pub fn parse_float(
num: Symbol,
fty: ast::FloatTy,
neg: bool,
) -> Result<Value, ()> {
let num = num.as_str();
use rustc_apfloat::ieee::{Single, Double};
use rustc_apfloat::Float;
let bits = match fty {
ast::FloatTy::F32 => {
num.parse::<f32>().map_err(|_| ())?;
let mut f = num.parse::<Single>().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::<f64>().map_err(|_| ())?;
let mut f = num.parse::<Double>().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)))
}
9 changes: 5 additions & 4 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
@@ -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)),
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}

62 changes: 32 additions & 30 deletions src/librustc_mir/interpret/operator.rs
Original file line number Diff line number Diff line change
@@ -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<fn(&i128, &i128) -> 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<fn(i128, i128) -> (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,
};

13 changes: 7 additions & 6 deletions src/librustc_mir/interpret/terminator/mod.rs
Original file line number Diff line number Diff line change
@@ -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!(),
};
}
}
2 changes: 0 additions & 2 deletions src/librustc_mir/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
14 changes: 8 additions & 6 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
@@ -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,
9 changes: 7 additions & 2 deletions src/librustc_mir/transform/generator.rs
Original file line number Diff line number Diff line change
@@ -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);

1 change: 0 additions & 1 deletion src/librustc_passes/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
1 change: 0 additions & 1 deletion src/librustc_passes/lib.rs
Original file line number Diff line number Diff line change
@@ -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]
13 changes: 9 additions & 4 deletions src/librustc_passes/mir_stats.rs
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 0 additions & 1 deletion src/librustc_trans/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
1 change: 0 additions & 1 deletion src/librustc_trans/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
30 changes: 5 additions & 25 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
@@ -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,
5 changes: 4 additions & 1 deletion src/librustc_trans/mir/rvalue.rs
Original file line number Diff line number Diff line change
@@ -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);
1 change: 0 additions & 1 deletion src/librustc_typeck/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
1 change: 0 additions & 1 deletion src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
1 change: 0 additions & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion src/test/ui/const-eval/index_out_of_bound.stderr
Original file line number Diff line number Diff line change
@@ -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

12 changes: 6 additions & 6 deletions src/test/ui/const-eval/promoted_errors.stderr
Original file line number Diff line number Diff line change
@@ -2,21 +2,21 @@ 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

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

1 change: 0 additions & 1 deletion src/test/ui/error-codes/E0080.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@ enum Enum {
//~| const_err
//~| const_err
//~| const_err
//~| divide by zero
}

fn main() {
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0080.stderr
Original file line number Diff line number Diff line change
@@ -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