Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
dee5024
Avoid ICE when `FnCtxt::local_ty` cannot find type; issue error then,…
pnkfelix Feb 22, 2015
00ccc7a
Make `test/run-pass/backtrace.rs` more robust about own host environm…
pnkfelix Feb 19, 2015
cdfff9d
rustc: implement arithmetic overflow checking
emberian Jan 6, 2015
1246d40
Add `core::num::wrapping` and fix overflow errors.
Aatch Jan 9, 2015
280dea7
Implement parse_opt_bool better
Aatch Jan 9, 2015
6d6038a
Added `OverflowingOps` trait to core::num::wrapping.
pnkfelix Feb 19, 2015
eadc8a7
fix Iter::rposition for new arith-overflow checking.
pnkfelix Feb 18, 2015
cf18e9c
fix test generic-extern-mangle.rs
nikomatsakis Feb 18, 2015
e7c9861
Fixes to collections to accommodate arith-overflow changes.
pnkfelix Feb 19, 2015
4394720
Fix the overflowing tests in run-fail.
pnkfelix Feb 19, 2015
c8db89a
Accommodate arith-overflow in `core::num`, `std::num`, `coretest::num`.
pnkfelix Feb 19, 2015
7c8edab
Accommodate arith-overflow in serialize::json numeric parsing.
pnkfelix Feb 19, 2015
6189e99
Accommodate arith-overflow in `rand` and `std::rand`.
pnkfelix Feb 19, 2015
f0404c3
`core::iter`: fix bug uncovered by arith-overflow.
pnkfelix Feb 20, 2015
faf3bcd
Accommodate simple cases of arith-overflow in `rustc` related crates.
pnkfelix Feb 20, 2015
f1ea2b3
Catch arith-overflow explicitly during `rustc::middle::const_eval`.
pnkfelix Feb 20, 2015
f9bbef7
Avoid fatal errors in astconv; just err and return `ty_err` instead.
pnkfelix Feb 22, 2015
e919f82
Address arith-overflow and error-handling in `const_eval.rs`.
pnkfelix Feb 22, 2015
5d950bd
Switch to `eval_const_expr_partial` when `check_match.rs` checks for …
pnkfelix Feb 22, 2015
46de12a
Switch to eval_const_expr_partial in `trans::consts`.
pnkfelix Feb 22, 2015
8491c82
Update tests for const-eval error handling changes.
pnkfelix Feb 22, 2015
b85b3c9
Fix span typo in the arithmetic overflow for array length reporting.
pnkfelix Feb 27, 2015
11057fe
Incorporated first review sugestion from eddyb.
pnkfelix Feb 27, 2015
4e23179
Incorporated second review suggestion from eddyb.
pnkfelix Mar 1, 2015
185c074
Fix backtrace tests for Linux
Manishearth Mar 2, 2015
243c516
sidestep potential over- and underflow in estimated stack bounds.
pnkfelix Mar 3, 2015
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
Prev Previous commit
Next Next commit
Incorporated first review sugestion from eddyb.
Suggestion was here:

  #22532 (comment)
  • Loading branch information
pnkfelix committed Mar 3, 2015
commit 11057fee08a6de23edbb8cb188336c104b4d25f9
134 changes: 34 additions & 100 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,106 +283,40 @@ impl ConstEvalErr {
}
}

fn invalid_op_for_bools(e: &Expr, op: ast::BinOp_) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::InvalidOpForBools(op) }
}
fn invalid_op_for_floats(e: &Expr, op: ast::BinOp_) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::InvalidOpForFloats(op) }
}
fn invalid_op_for_int_uint(e: &Expr, op: ast::BinOp_) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::InvalidOpForIntUint(op) }
}
fn invalid_op_for_uint_int(e: &Expr, op: ast::BinOp_) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::InvalidOpForUintInt(op) }
}
fn negate_on_string(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::NegateOnString }
}
fn negate_on_boolean(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::NegateOnBoolean }
}
fn not_on_float(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::NotOnFloat }
}
fn not_on_string(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::NotOnString }
}

fn addi_with_overflow(e: &Expr, a: i64, b: i64) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::AddiWithOverflow(a, b) }
}
fn subi_with_overflow(e: &Expr, a: i64, b: i64) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::SubiWithOverflow(a, b) }
}
fn muli_with_overflow(e: &Expr, a: i64, b: i64) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::MuliWithOverflow(a, b) }
}
fn addu_with_overflow(e: &Expr, a: u64, b: u64) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::AdduWithOverflow(a, b) }
}
fn subu_with_overflow(e: &Expr, a: u64, b: u64) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::SubuWithOverflow(a, b) }
}
fn mulu_with_overflow(e: &Expr, a: u64, b: u64) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::MuluWithOverflow(a, b) }
}
fn divide_by_zero(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::DivideByZero }
}
fn divide_with_overflow(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::DivideWithOverflow }
}
fn modulo_by_zero(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::ModuloByZero }
}
fn modulo_with_overflow(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::ModuloWithOverflow }
}
fn missing_struct_field(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::MissingStructField }
}
fn non_const_path(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::NonConstPath }
}
fn non_const_struct(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::NonConstStruct }
}
fn tuple_index_out_of_bounds(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::TupleIndexOutOfBounds }
}
macro_rules! signal {
($e:expr, $ctor:ident) => {
return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor })
};

fn misc_binary_op(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::MiscBinaryOp }
}
fn misc_catch_all(e: &Expr) -> ConstEvalErr {
ConstEvalErr { span: e.span, kind: ErrKind::MiscCatchAll }
($e:expr, $ctor:ident($($arg:expr),*)) => {
return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor($($arg),*) })
}
}


fn checked_add_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_add(b);
if !oflo { Ok(const_int(ret)) } else { Err(addi_with_overflow(e, a, b)) }
if !oflo { Ok(const_int(ret)) } else { signal!(e, AddiWithOverflow(a, b)) }
}
fn checked_sub_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_sub(b);
if !oflo { Ok(const_int(ret)) } else { Err(subi_with_overflow(e, a, b)) }
if !oflo { Ok(const_int(ret)) } else { signal!(e, SubiWithOverflow(a, b)) }
}
fn checked_mul_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_mul(b);
if !oflo { Ok(const_int(ret)) } else { Err(muli_with_overflow(e, a, b)) }
if !oflo { Ok(const_int(ret)) } else { signal!(e, MuliWithOverflow(a, b)) }
}

fn checked_add_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_add(b);
if !oflo { Ok(const_uint(ret)) } else { Err(addu_with_overflow(e, a, b)) }
if !oflo { Ok(const_uint(ret)) } else { signal!(e, AdduWithOverflow(a, b)) }
}
fn checked_sub_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_sub(b);
if !oflo { Ok(const_uint(ret)) } else { Err(subu_with_overflow(e, a, b)) }
if !oflo { Ok(const_uint(ret)) } else { signal!(e, SubuWithOverflow(a, b)) }
}
fn checked_mul_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_mul(b);
if !oflo { Ok(const_uint(ret)) } else { Err(mulu_with_overflow(e, a, b)) }
if !oflo { Ok(const_uint(ret)) } else { signal!(e, MuluWithOverflow(a, b)) }
}


Expand All @@ -400,8 +334,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
Ok(const_float(f)) => Ok(const_float(-f)),
Ok(const_int(i)) => Ok(const_int(-i)),
Ok(const_uint(i)) => Ok(const_uint(-i)),
Ok(const_str(_)) => Err(negate_on_string(e)),
Ok(const_bool(_)) => Err(negate_on_boolean(e)),
Ok(const_str(_)) => signal!(e, NegateOnString),
Ok(const_bool(_)) => signal!(e, NegateOnBoolean),
err => err
}
}
Expand All @@ -410,8 +344,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
Ok(const_int(i)) => Ok(const_int(!i)),
Ok(const_uint(i)) => Ok(const_uint(!i)),
Ok(const_bool(b)) => Ok(const_bool(!b)),
Ok(const_str(_)) => Err(not_on_string(e)),
Ok(const_float(_)) => Err(not_on_float(e)),
Ok(const_str(_)) => signal!(e, NotOnString),
Ok(const_float(_)) => signal!(e, NotOnFloat),
err => err
}
}
Expand All @@ -435,7 +369,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
ast::BiNe => fromb(a != b),
ast::BiGe => fromb(a >= b),
ast::BiGt => fromb(a > b),
_ => Err(invalid_op_for_floats(e, op.node)),
_ => signal!(e, InvalidOpForFloats(op.node))
}
}
(Ok(const_int(a)), Ok(const_int(b))) => {
Expand Down Expand Up @@ -463,18 +397,18 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
ast::BiMul => checked_mul_int(e, a, b),
ast::BiDiv => {
if b == 0 {
Err(divide_by_zero(e))
signal!(e, DivideByZero);
} else if b == -1 && is_a_min_value() {
Err(divide_with_overflow(e))
signal!(e, DivideWithOverflow);
} else {
Ok(const_int(a / b))
}
}
ast::BiRem => {
if b == 0 {
Err(modulo_by_zero(e))
signal!(e, ModuloByZero)
} else if b == -1 && is_a_min_value() {
Err(modulo_with_overflow(e))
signal!(e, ModuloWithOverflow)
} else {
Ok(const_int(a % b))
}
Expand All @@ -497,9 +431,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
ast::BiAdd => checked_add_uint(e, a, b),
ast::BiSub => checked_sub_uint(e, a, b),
ast::BiMul => checked_mul_uint(e, a, b),
ast::BiDiv if b == 0 => Err(divide_by_zero(e)),
ast::BiDiv if b == 0 => signal!(e, DivideByZero),
ast::BiDiv => Ok(const_uint(a / b)),
ast::BiRem if b == 0 => Err(modulo_by_zero(e)),
ast::BiRem if b == 0 => signal!(e, ModuloByZero),
ast::BiRem => Ok(const_uint(a % b)),
ast::BiAnd | ast::BiBitAnd => Ok(const_uint(a & b)),
ast::BiOr | ast::BiBitOr => Ok(const_uint(a | b)),
Expand All @@ -519,14 +453,14 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
match op.node {
ast::BiShl => Ok(const_int(a << b as uint)),
ast::BiShr => Ok(const_int(a >> b as uint)),
_ => Err(invalid_op_for_int_uint(e, op.node)),
_ => signal!(e, InvalidOpForIntUint(op.node)),
}
}
(Ok(const_uint(a)), Ok(const_int(b))) => {
match op.node {
ast::BiShl => Ok(const_uint(a << b as uint)),
ast::BiShr => Ok(const_uint(a >> b as uint)),
_ => Err(invalid_op_for_uint_int(e, op.node)),
_ => signal!(e, InvalidOpForUintInt(op.node)),
}
}
(Ok(const_bool(a)), Ok(const_bool(b))) => {
Expand All @@ -538,13 +472,13 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
ast::BiBitOr => a | b,
ast::BiEq => a == b,
ast::BiNe => a != b,
_ => return Err(invalid_op_for_bools(e, op.node)),
_ => signal!(e, InvalidOpForBools(op.node)),
}))
}
(err @ Err(..), _) |
(_, err @ Err(..)) => err,

_ => Err(misc_binary_op(e)),
_ => signal!(e, MiscBinaryOp),
}
}
ast::ExprCast(ref base, ref target_ty) => {
Expand Down Expand Up @@ -589,7 +523,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
};
let const_expr = match const_expr {
Some(actual_e) => actual_e,
None => return Err(non_const_path(e)),
None => signal!(e, NonConstPath)
};
let ety = ety.or_else(|| const_ty.and_then(|ty| ast_ty_to_prim_ty(tcx, ty)));
eval_const_expr_partial(tcx, const_expr, ety)
Expand All @@ -611,11 +545,11 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
if fields.len() > index.node {
return eval_const_expr_partial(tcx, &*fields[index.node], None)
} else {
return Err(tuple_index_out_of_bounds(e))
signal!(e, TupleIndexOutOfBounds);
}
}

Err(non_const_struct(e))
signal!(e, NonConstStruct);
}
ast::ExprField(ref base, field_name) => {
// Get the base expression if it is a struct and it is constant
Expand All @@ -626,13 +560,13 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
f.ident.node.as_str() == field_name.node.as_str()) {
return eval_const_expr_partial(tcx, &*f.expr, None)
} else {
return Err(missing_struct_field(e));
signal!(e, MissingStructField);
}
}

Err(non_const_struct(e))
signal!(e, NonConstStruct);
}
_ => Err(misc_catch_all(e))
_ => signal!(e, MiscCatchAll)
}
}

Expand Down