1
Fork 0

Unify MIR assert messages and const eval errors

This commit is contained in:
Oliver Schneider 2018-04-27 15:21:31 +02:00 committed by Oliver Schneider
parent 5f46e5cc7e
commit 01158eaec6
No known key found for this signature in database
GPG key ID: 1D5CB4FC597C3004
16 changed files with 111 additions and 147 deletions

View file

@ -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>>

View file

@ -535,8 +535,8 @@ for ::mir::interpret::EvalError<'gcx> {
}
}
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
for ::mir::interpret::EvalErrorKind<'gcx> {
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>) {
@ -578,6 +578,8 @@ for ::mir::interpret::EvalErrorKind<'gcx> {
OverflowNeg |
RemainderByZero |
DivisionByZero |
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic |
ReferencedConstant => {}
MachineError(ref err) => err.hash_stable(hcx, hasher),
FunctionPointerTyMismatch(a, b) => {
@ -597,10 +599,9 @@ for ::mir::interpret::EvalErrorKind<'gcx> {
},
InvalidBoolOp(bop) => bop.hash_stable(hcx, hasher),
Unimplemented(ref s) => s.hash_stable(hcx, hasher),
ArrayIndexOutOfBounds(sp, a, b) => {
sp.hash_stable(hcx, hasher);
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher)
BoundsCheck { ref len, ref index } => {
len.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher)
},
Intrinsic(ref s) => s.hash_stable(hcx, hasher),
InvalidChar(c) => c.hash_stable(hcx, hasher),

View file

@ -7,17 +7,16 @@ use super::{
MemoryPointer, Lock, AccessKind
};
use syntax::codemap::Span;
use backtrace::Backtrace;
#[derive(Debug, Clone)]
pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx>,
pub kind: EvalErrorKind<'tcx, u64>,
pub backtrace: Option<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
@ -29,8 +28,10 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
}
}
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
pub enum EvalErrorKind<'tcx> {
pub type AssertMessage<'tcx> = EvalErrorKind<'tcx, mir::Operand<'tcx>>;
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum EvalErrorKind<'tcx, O> {
/// This variant is used by machines to signal their own errors that do not
/// match an existing variant
MachineError(String),
@ -58,7 +59,7 @@ pub enum EvalErrorKind<'tcx> {
Unimplemented(String),
DerefFunctionPointer,
ExecuteMemory,
ArrayIndexOutOfBounds(Span, u64, u64),
BoundsCheck { len: O, index: O },
Overflow(mir::BinOp),
OverflowNeg,
DivisionByZero,
@ -121,11 +122,13 @@ pub enum EvalErrorKind<'tcx> {
/// Cannot compute this constant because it depends on another one
/// which already produced an error
ReferencedConstant,
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
}
pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
impl<'tcx> EvalErrorKind<'tcx> {
impl<'tcx, O> EvalErrorKind<'tcx, O> {
pub fn description(&self) -> &str {
use self::EvalErrorKind::*;
match *self {
@ -175,7 +178,7 @@ impl<'tcx> EvalErrorKind<'tcx> {
"tried to dereference a function pointer",
ExecuteMemory =>
"tried to treat a memory pointer as a function pointer",
ArrayIndexOutOfBounds(..) =>
BoundsCheck{..} =>
"array index out of bounds",
Intrinsic(..) =>
"intrinsic failed",
@ -228,7 +231,7 @@ impl<'tcx> EvalErrorKind<'tcx> {
"the evaluated program panicked",
ReadFromReturnPointer =>
"tried to read from the return pointer",
EvalErrorKind::PathNotFound(_) =>
PathNotFound(_) =>
"a path could not be resolved, maybe the crate is not loaded",
UnimplementedTraitSelection =>
"there were unresolved type arguments during trait selection",
@ -247,14 +250,22 @@ impl<'tcx> EvalErrorKind<'tcx> {
Overflow(op) => bug!("{:?} cannot overflow", op),
DivisionByZero => "attempt to divide by zero",
RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
GeneratorResumedAfterReturn => "generator resumed after completion",
GeneratorResumedAfterPanic => "generator resumed after panicking",
}
}
}
impl<'tcx> fmt::Display for EvalError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.kind)
}
}
impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::EvalErrorKind::*;
match self.kind {
match *self {
PointerOutOfBounds { ptr, access, allocation_size } => {
write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}",
if access { "memory access" } else { "pointer computed" },
@ -282,8 +293,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
FunctionPointerTyMismatch(sig, got) =>
write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
ArrayIndexOutOfBounds(span, len, index) =>
write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
BoundsCheck { ref len, ref index } =>
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
ReallocatedWrongMemoryKind(ref old, ref new) =>
write!(f, "tried to reallocate memory from {} to {}", old, new),
DeallocatedWrongMemoryKind(ref old, ref new) =>
@ -305,7 +316,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
write!(f, "{}", inner),
IncorrectAllocationInformation(size, size2, align, align2) =>
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2),
_ => write!(f, "{}", self.kind.description()),
_ => write!(f, "{}", self.description()),
}
}
}

View file

@ -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};

View file

@ -45,6 +45,8 @@ use syntax_pos::{Span, DUMMY_SP};
use rustc_apfloat::ieee::{Single, Double};
use rustc_apfloat::Float;
pub use mir::interpret::AssertMessage;
mod cache;
pub mod tcx;
pub mod visit;
@ -1132,23 +1134,7 @@ impl<'tcx> TerminatorKind<'tcx> {
write!(fmt, "!")?;
}
write!(fmt, "{:?}, ", cond)?;
match *msg {
AssertMessage::BoundsCheck { ref len, ref index } => {
write!(fmt, "{:?}, {:?}, {:?}",
"index out of bounds: the len is {} but the index is {}",
len, index)?;
}
AssertMessage::Math(ref err) => {
write!(fmt, "{:?}", err.description())?;
}
AssertMessage::GeneratorResumedAfterReturn => {
write!(fmt, "{:?}", "generator resumed after completion")?;
}
AssertMessage::GeneratorResumedAfterPanic => {
write!(fmt, "{:?}", "generator resumed after panicking")?;
}
}
write!(fmt, "{:?}", msg)?;
write!(fmt, ")")
},
@ -1205,17 +1191,6 @@ impl<'tcx> TerminatorKind<'tcx> {
}
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum AssertMessage<'tcx> {
BoundsCheck {
len: Operand<'tcx>,
index: Operand<'tcx>
},
Math(EvalErrorKind<'tcx>),
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
}
///////////////////////////////////////////////////////////////////////////
// Statements
@ -2281,8 +2256,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
}
},
Assert { ref cond, expected, ref msg, target, cleanup } => {
let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
AssertMessage::BoundsCheck {
let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
EvalErrorKind::BoundsCheck {
len: len.fold_with(folder),
index: index.fold_with(folder),
}
@ -2331,7 +2306,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
},
Assert { ref cond, ref msg, .. } => {
if cond.visit_with(visitor) {
if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
len.visit_with(visitor) || index.visit_with(visitor)
} else {
false

View file

@ -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);
}
}

View file

@ -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,7 +514,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
Unimplemented(ref s) => Unimplemented(s.clone()),
DerefFunctionPointer => DerefFunctionPointer,
ExecuteMemory => ExecuteMemory,
ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b),
BoundsCheck { ref len, ref index } => BoundsCheck {
len: tcx.lift(len)?,
index: tcx.lift(index)?,
},
Intrinsic(ref s) => Intrinsic(s.clone()),
InvalidChar(c) => InvalidChar(c),
StackFrameLimitReached => StackFrameLimitReached,
@ -570,10 +583,8 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
Overflow(op) => Overflow(op),
DivisionByZero => DivisionByZero,
RemainderByZero => RemainderByZero,
};
Some(interpret::EvalError {
kind: kind,
backtrace: self.backtrace.clone(),
GeneratorResumedAfterReturn => GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic => GeneratorResumedAfterPanic,
})
}
}

View file

@ -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,
);
}
}

View file

@ -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)
}

View file

@ -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))
};

View file

@ -85,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
this.cfg.push_assign(block, source_info, &is_min,
Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval));
let err = EvalErrorKind::OverflowNeg;
block = this.assert(block, Operand::Move(is_min), false,
AssertMessage::Math(err), expr_span);
EvalErrorKind::OverflowNeg, expr_span);
}
block.and(Rvalue::UnaryOp(op, arg))
}
@ -313,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let err = EvalErrorKind::Overflow(op);
block = self.assert(block, Operand::Move(of), false,
AssertMessage::Math(err), span);
err, span);
block.and(Rvalue::Use(Operand::Move(val)))
} else {
@ -336,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero));
block = self.assert(block, Operand::Move(is_zero), false,
AssertMessage::Math(zero_err), span);
zero_err, span);
// We only need to check for the overflow in one case:
// MIN / -1, and only for signed values.
@ -361,7 +360,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min));
block = self.assert(block, Operand::Move(of), false,
AssertMessage::Math(overflow_err), span);
overflow_err, span);
}
}

View file

@ -148,21 +148,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
if expected == cond_val {
self.goto_block(target);
} else {
use rustc::mir::AssertMessage::*;
use rustc::mir::interpret::EvalErrorKind::*;
return match *msg {
BoundsCheck { ref len, ref index } => {
let span = terminator.source_info.span;
let len = self.eval_operand_to_primval(len)
.expect("can't eval len")
.to_u64()?;
let index = self.eval_operand_to_primval(index)
.expect("can't eval index")
.to_u64()?;
err!(ArrayIndexOutOfBounds(span, len, index))
err!(BoundsCheck { len, index })
}
Math(ref err) => Err(err.clone().into()),
Overflow(op) => Err(Overflow(op).into()),
OverflowNeg => Err(OverflowNeg.into()),
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic => unimplemented!(),
_ => bug!(),
};
}
}

View file

@ -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,

View file

@ -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);

View file

@ -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);
}

View file

@ -13,6 +13,7 @@ use rustc::middle::lang_items;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::layout::{self, LayoutOf};
use rustc::mir;
use rustc::mir::interpret::EvalErrorKind;
use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode};
use base;
use callee;
@ -311,9 +312,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
// checked operation, just a comparison with the minimum
// value, so we have to check for the assert message.
if !bx.cx.check_overflow {
use rustc::mir::interpret::EvalErrorKind::OverflowNeg;
if let mir::AssertMessage::Math(OverflowNeg) = *msg {
if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
const_cond = Some(expected);
}
}
@ -353,7 +352,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
// Put together the arguments to the panic entry point.
let (lang_item, args) = match *msg {
mir::AssertMessage::BoundsCheck { ref len, ref index } => {
EvalErrorKind::BoundsCheck { ref len, ref index } => {
let len = self.trans_operand(&mut bx, len).immediate();
let index = self.trans_operand(&mut bx, index).immediate();
@ -365,26 +364,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
(lang_items::PanicBoundsCheckFnLangItem,
vec![file_line_col, index, len])
}
mir::AssertMessage::Math(ref err) => {
let msg_str = Symbol::intern(err.description()).as_str();
let msg_str = C_str_slice(bx.cx, msg_str);
let msg_file_line_col = C_struct(bx.cx,
&[msg_str, filename, line, col],
false);
let msg_file_line_col = consts::addr_of(bx.cx,
msg_file_line_col,
align,
"panic_loc");
(lang_items::PanicFnLangItem,
vec![msg_file_line_col])
}
mir::AssertMessage::GeneratorResumedAfterReturn |
mir::AssertMessage::GeneratorResumedAfterPanic => {
let str = if let mir::AssertMessage::GeneratorResumedAfterReturn = *msg {
"generator resumed after completion"
} else {
"generator resumed after panicking"
};
_ => {
let str = msg.description();
let msg_str = Symbol::intern(str).as_str();
let msg_str = C_str_slice(bx.cx, msg_str);
let msg_file_line_col = C_struct(bx.cx,