From ee983230c965de4f45032a1bdb852a23dae0dbad Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Apr 2016 11:17:32 +0200 Subject: [PATCH 1/7] report shift right error instead of shift left error on right shift --- src/librustc_const_math/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index 658d4d9a6d2fa..64f03be3b5f07 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -503,7 +503,7 @@ impl ::std::ops::Shr for ConstInt { I8(a) => Ok(I8(overflowing!(a.overflowing_shr(b), Op::Shr))), I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))), I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))), - I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shl))), + I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))), Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))), Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))), U8(a) => Ok(U8(overflowing!(a.overflowing_shr(b), Op::Shr))), From 3acee3b6c5381d84fe4ad68e077517bd0975333d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Apr 2016 11:18:48 +0200 Subject: [PATCH 2/7] const_err lint all constant expressions --- src/librustc_passes/consts.rs | 45 +++++++++---------- src/test/compile-fail/const-err-early.rs | 2 +- src/test/compile-fail/const-err.rs | 1 - .../compile-fail/lint-exceeding-bitshifts.rs | 21 +++++++++ src/test/compile-fail/lint-type-overflow2.rs | 2 + 5 files changed, 44 insertions(+), 27 deletions(-) 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 From 735c018974e5570ea13fd887aa70a011a5b8e7b8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Apr 2016 14:09:05 +0200 Subject: [PATCH 3/7] skip double negation in const eval --- src/librustc_const_eval/eval.rs | 83 +++++++++++--------- src/test/compile-fail/lint-type-overflow2.rs | 1 - 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 3f68f6aeccace..c2ac3d838c8d0 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -562,44 +562,51 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>, let result = match e.node { hir::ExprUnary(hir::UnNeg, ref inner) => { // unary neg literals already got their sign during creation - if let hir::ExprLit(ref lit) = inner.node { - use syntax::ast::*; - use syntax::ast::LitIntType::*; - const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; - const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; - const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; - const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; - match (&lit.node, ety.map(|t| &t.sty)) { - (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | - (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { - return Ok(Integral(I8(::std::i8::MIN))) - }, - (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | - (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { - return Ok(Integral(I16(::std::i16::MIN))) - }, - (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | - (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { - return Ok(Integral(I32(::std::i32::MIN))) - }, - (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | - (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { - return Ok(Integral(I64(::std::i64::MIN))) - }, - (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | - (&LitKind::Int(n, Signed(IntTy::Is)), _) => { - match tcx.sess.target.int_type { - IntTy::I32 => if n == I32_OVERFLOW { - return Ok(Integral(Isize(Is32(::std::i32::MIN)))); - }, - IntTy::I64 => if n == I64_OVERFLOW { - return Ok(Integral(Isize(Is64(::std::i64::MIN)))); - }, - _ => bug!(), - } - }, - _ => {}, - } + match inner.node { + hir::ExprLit(ref lit) => { + use syntax::ast::*; + use syntax::ast::LitIntType::*; + const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; + const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; + const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; + const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; + match (&lit.node, ety.map(|t| &t.sty)) { + (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | + (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { + return Ok(Integral(I8(::std::i8::MIN))) + }, + (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | + (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { + return Ok(Integral(I16(::std::i16::MIN))) + }, + (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | + (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { + return Ok(Integral(I32(::std::i32::MIN))) + }, + (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | + (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { + return Ok(Integral(I64(::std::i64::MIN))) + }, + (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | + (&LitKind::Int(n, Signed(IntTy::Is)), _) => { + match tcx.sess.target.int_type { + IntTy::I32 => if n == I32_OVERFLOW { + return Ok(Integral(Isize(Is32(::std::i32::MIN)))); + }, + IntTy::I64 => if n == I64_OVERFLOW { + return Ok(Integral(Isize(Is64(::std::i64::MIN)))); + }, + _ => bug!(), + } + }, + _ => {}, + } + }, + hir::ExprUnary(hir::UnNeg, ref inner) => { + // skip `--$expr` + return eval_const_expr_partial(tcx, inner, ty_hint, fn_args); + }, + _ => {}, } match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { Float(f) => Float(-f), diff --git a/src/test/compile-fail/lint-type-overflow2.rs b/src/test/compile-fail/lint-type-overflow2.rs index e99dfb9aa0f0e..9499d732a3835 100644 --- a/src/test/compile-fail/lint-type-overflow2.rs +++ b/src/test/compile-fail/lint-type-overflow2.rs @@ -15,7 +15,6 @@ #[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 From 89d1046503b2721e7a372f24eb7ef5998d9dd176 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Apr 2016 14:10:07 +0200 Subject: [PATCH 4/7] don't report bitshift overflow twice --- src/librustc_const_math/lib.rs | 2 +- src/librustc_passes/consts.rs | 5 ++++- src/librustc_passes/lib.rs | 1 + .../compile-fail/lint-exceeding-bitshifts.rs | 20 ------------------- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 9f66aac6e3899..59792d16e8bb6 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -40,4 +40,4 @@ mod err; pub use int::*; pub use us::*; pub use is::*; -pub use err::ConstMathErr; +pub use err::{ConstMathErr, Op}; diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 32bcac40289eb..0673188f53d6f 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -28,9 +28,10 @@ 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, MiscCatchAll}; use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp}; +use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_math::{ConstMathErr, Op}; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::middle::expr_use_visitor as euv; @@ -490,6 +491,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { Err(ConstEvalErr { kind: MiscCatchAll, ..}) | Err(ConstEvalErr { kind: MiscBinaryOp, ..}) | Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), ..}) | + Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), ..}) | + Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), ..}) | Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {}, Err(msg) => { self.qualif = self.qualif | ConstQualif::NOT_CONST; diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 53ae1b30f7c17..b235962eb9a3d 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -30,6 +30,7 @@ extern crate core; #[macro_use] extern crate rustc; extern crate rustc_const_eval; +extern crate rustc_const_math; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs index a3ae0671c54cb..6d5abc944e78f 100644 --- a/src/test/compile-fail/lint-exceeding-bitshifts.rs +++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs @@ -16,53 +16,37 @@ 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; @@ -73,7 +57,6 @@ fn main() { 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; @@ -81,14 +64,11 @@ 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 } From 9d7ed99c06bbce263c4de56e269b62b135c5a6e1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Apr 2016 14:11:14 +0200 Subject: [PATCH 5/7] skip non-const-path errors for now Associated constants aren't implemented fully in early const eval --- src/librustc_passes/consts.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 0673188f53d6f..9b71445270aca 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -28,8 +28,9 @@ 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::{ErroneousReferencedConstant, MiscBinaryOp}; use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; +use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; +use rustc_const_eval::ErrKind::UnresolvedPath; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_math::{ConstMathErr, Op}; use rustc::hir::def::Def; @@ -490,6 +491,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { Err(ConstEvalErr { kind: UnimplementedConstVal(_), ..}) | Err(ConstEvalErr { kind: MiscCatchAll, ..}) | Err(ConstEvalErr { kind: MiscBinaryOp, ..}) | + Err(ConstEvalErr { kind: NonConstPath, ..}) | + Err(ConstEvalErr { kind: UnresolvedPath, ..}) | Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), ..}) | Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), ..}) | Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), ..}) | From d3c489c917c1086728001c94a98765e02171a201 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Apr 2016 15:32:18 +0200 Subject: [PATCH 6/7] don't demote expressions just because const_eval fails this might introduce subtle bugs to code generation --- src/librustc_passes/consts.rs | 1 - src/test/compile-fail/const-err.rs | 5 +++++ src/test/compile-fail/const-err2.rs | 34 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/const-err2.rs diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 9b71445270aca..1f9c40856fd19 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -498,7 +498,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), ..}) | 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()) diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs index 816799eabf792..3fb9a3f236ced 100644 --- a/src/test/compile-fail/const-err.rs +++ b/src/test/compile-fail/const-err.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// these errors are not actually "const_err", they occur in trans/consts +// and are unconditional warnings that can't be denied or allowed + #![feature(rustc_attrs)] #![allow(exceeding_bitshifts)] +#![allow(const_err)] fn black_box(_: T) { unimplemented!() @@ -21,6 +25,7 @@ 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/const-err2.rs b/src/test/compile-fail/const-err2.rs new file mode 100644 index 0000000000000..f0d65f1424c46 --- /dev/null +++ b/src/test/compile-fail/const-err2.rs @@ -0,0 +1,34 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(exceeding_bitshifts)] +#![deny(const_err)] + +fn black_box(_: T) { + unimplemented!() +} + +fn main() { + let a = -std::i8::MIN; + //~^ ERROR attempted to negate with overflow + let b = 200u8 + 200u8 + 200u8; + //~^ ERROR attempted to add with overflow + //~| ERROR attempted to add with overflow + let c = 200u8 * 4; + //~^ ERROR attempted to multiply with overflow + let d = 42u8 - (42u8 + 1); + //~^ ERROR attempted to subtract with overflow + let _e = [5u8][1]; + black_box(a); + black_box(b); + black_box(c); + black_box(d); +} From 5cdcad9d357aa59ce0423b4f68cb9386310aba73 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 27 Apr 2016 10:47:46 +0200 Subject: [PATCH 7/7] update Cargo.toml for rustbuild --- src/librustc_passes/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index fa6bd3dfb67dd..0c85ffd2e9c39 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -12,4 +12,5 @@ crate-type = ["dylib"] log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_const_eval = { path = "../librustc_const_eval" } +rustc_const_math = { path = "../librustc_const_math" } syntax = { path = "../libsyntax" }