Auto merge of #50198 - oli-obk:const_prop, r=eddyb

Remove some unused code
This commit is contained in:
bors 2018-05-01 12:16:14 +00:00
commit 0d8321b5e8
47 changed files with 270 additions and 727 deletions

14
src/Cargo.lock generated
View File

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

View File

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

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
});

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

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

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

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

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

View File

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

View File

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

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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",
}
}
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Ordering, ConstMathErr> {
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<Self, ParseFloatError> {
let bits = match ty {
ast::FloatTy::F32 => {
let rust_bits = num.parse::<f32>()?.to_bits() as u128;
let apfloat = num.parse::<Single>().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::<f64>()?.to_bits() as u128;
let apfloat = num.parse::<Double>().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<i128> {
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<u128> {
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<Self, ConstMathErr>;
fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
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);

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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};

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,7 +15,6 @@ enum Enum {
//~| const_err
//~| const_err
//~| const_err
//~| divide by zero
}
fn main() {

View File

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