diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 2fa7f026a521a..32bcac40289eb 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -28,8 +28,8 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::{CastKind}; use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs}; use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id}; -use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal}; -use rustc_const_eval::ErrKind::ErroneousReferencedConstant; +use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll}; +use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp}; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; @@ -437,29 +437,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { } intravisit::walk_expr(self, ex); } - // Division by zero and overflow checking. - hir::ExprBinary(op, _, _) => { - intravisit::walk_expr(self, ex); - let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem; - match node_ty.sty { - ty::TyUint(_) | ty::TyInt(_) if div_or_rem => { - if !self.qualif.intersects(ConstQualif::NOT_CONST) { - match eval_const_expr_partial( - self.tcx, ex, ExprTypeChecked, None) { - Ok(_) => {} - Err(ConstEvalErr { kind: UnimplementedConstVal(_), ..}) | - Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {}, - Err(msg) => { - self.tcx.sess.add_lint(CONST_ERR, ex.id, - msg.span, - msg.description().into_owned()) - } - } - } - } - _ => {} - } - } _ => intravisit::walk_expr(self, ex) } @@ -505,6 +482,24 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { } None => {} } + + if self.mode == Mode::Var && !self.qualif.intersects(ConstQualif::NOT_CONST) { + match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) { + Ok(_) => {} + Err(ConstEvalErr { kind: UnimplementedConstVal(_), ..}) | + Err(ConstEvalErr { kind: MiscCatchAll, ..}) | + Err(ConstEvalErr { kind: MiscBinaryOp, ..}) | + Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), ..}) | + Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {}, + Err(msg) => { + self.qualif = self.qualif | ConstQualif::NOT_CONST; + self.tcx.sess.add_lint(CONST_ERR, ex.id, + msg.span, + msg.description().into_owned()) + } + } + } + self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif); // Don't propagate certain flags. self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS); diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs index cdcdb919bdef5..7567791c24066 100644 --- a/src/test/compile-fail/const-err-early.rs +++ b/src/test/compile-fail/const-err-early.rs @@ -18,5 +18,5 @@ pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR attempted to subtract with overfl pub const E: u8 = [5u8][1]; //~ ERROR index out of bounds fn main() { - let _e = [6u8][1]; + let _e = [6u8][1]; //~ ERROR: array index out of bounds } diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs index 45e8fc37d878b..816799eabf792 100644 --- a/src/test/compile-fail/const-err.rs +++ b/src/test/compile-fail/const-err.rs @@ -21,7 +21,6 @@ fn main() { //~^ WARN attempted to negate with overflow let b = 200u8 + 200u8 + 200u8; //~^ WARN attempted to add with overflow - //~^^ WARN attempted to add with overflow let c = 200u8 * 4; //~^ WARN attempted to multiply with overflow let d = 42u8 - (42u8 + 1); diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs index e1ed21877c9f6..a3ae0671c54cb 100644 --- a/src/test/compile-fail/lint-exceeding-bitshifts.rs +++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs @@ -16,46 +16,64 @@ fn main() { let n = 1u8 << 7; let n = 1u8 << 8; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1u16 << 15; let n = 1u16 << 16; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1u32 << 31; let n = 1u32 << 32; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1u64 << 63; let n = 1u64 << 64; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1i8 << 7; let n = 1i8 << 8; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1i16 << 15; let n = 1i16 << 16; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1i32 << 31; let n = 1i32 << 32; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1i64 << 63; let n = 1i64 << 64; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1u8 >> 7; let n = 1u8 >> 8; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1u16 >> 15; let n = 1u16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1u32 >> 31; let n = 1u32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1u64 >> 63; let n = 1u64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1i8 >> 7; let n = 1i8 >> 8; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1i16 >> 15; let n = 1i16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1i32 >> 31; let n = 1i32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1i64 >> 63; let n = 1i64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow let n = 1u8; let n = n << 7; let n = n << 8; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u8 << -8; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift by a negative amount let n = 1u8 << (4+3); let n = 1u8 << (4+4); //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow #[cfg(target_pointer_width = "32")] const BITS: usize = 32; @@ -63,11 +81,14 @@ fn main() { const BITS: usize = 64; let n = 1_isize << BITS; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1_usize << BITS; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift left with overflow let n = 1i8<<(1isize+-1); let n = 1i64 >> [63][0]; let n = 1i64 >> [64][0]; //~ ERROR: bitshift exceeds the type's number of bits + //~^ WARN: attempted to shift right with overflow } diff --git a/src/test/compile-fail/lint-type-overflow2.rs b/src/test/compile-fail/lint-type-overflow2.rs index 83300f18c3e95..e99dfb9aa0f0e 100644 --- a/src/test/compile-fail/lint-type-overflow2.rs +++ b/src/test/compile-fail/lint-type-overflow2.rs @@ -10,10 +10,12 @@ // #![deny(overflowing_literals)] +#![deny(const_err)] #[allow(unused_variables)] fn main() { let x2: i8 = --128; //~ error: literal out of range for i8 + //~^ error: attempted to negate with overflow let x = -3.40282348e+38_f32; //~ error: literal out of range for f32 let x = 3.40282348e+38_f32; //~ error: literal out of range for f32