diff options
| author | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-03-06 12:43:02 +0100 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-03-08 08:35:39 +0100 |
| commit | b5ace9a906d0a445420a0ff16f77ce967722ddc6 (patch) | |
| tree | de379168cd41e525503f37c9196be4433057c9e2 | |
| parent | edc5f7343338ddbbc2bae94be585cd821dbe8118 (diff) | |
| download | rust-b5ace9a906d0a445420a0ff16f77ce967722ddc6.tar.gz rust-b5ace9a906d0a445420a0ff16f77ce967722ddc6.zip | |
Unify the const folding errors
before they differed depending on whether optimizations were on or not
24 files changed, 278 insertions, 155 deletions
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 565e5de85c1..c8e1a93cdda 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -12,10 +12,10 @@ //! assertion failures - +use rustc::hir::def::Def; use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local}; use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind}; -use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp}; +use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem}; use rustc::mir::visit::{Visitor, PlaceContext}; use rustc::middle::const_val::ConstVal; use rustc::ty::{TyCtxt, self, Instance}; @@ -26,6 +26,10 @@ use syntax::codemap::Span; use rustc::ty::subst::Substs; use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::ParamEnv; +use rustc::ty::layout::{ + LayoutOf, TyLayout, LayoutError, + HasTyCtxt, TargetDataLayout, HasDataLayout, +}; pub struct ConstProp; @@ -34,6 +38,15 @@ impl MirPass for ConstProp { tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, mir: &mut Mir<'tcx>) { + // will be evaluated by miri and produce its errors there + if source.promoted.is_some() { + return; + } + match tcx.describe_def(source.def_id) { + // skip statics because they'll be evaluated by miri anyway + Some(Def::Static(..)) => return, + _ => {}, + } trace!("ConstProp starting for {:?}", source.def_id); // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold @@ -59,6 +72,28 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> { param_env: ParamEnv<'tcx>, } +impl<'a, 'b, 'tcx> LayoutOf<ty::Ty<'tcx>> for &'a ConstPropagator<'a, 'b, 'tcx> { + type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>; + + fn layout_of(self, ty: ty::Ty<'tcx>) -> Self::TyLayout { + self.tcx.layout_of(self.param_env.and(ty)) + } +} + +impl<'a, 'b, 'tcx> HasDataLayout for &'a ConstPropagator<'a, 'b, 'tcx> { + #[inline] + fn data_layout(&self) -> &TargetDataLayout { + &self.tcx.data_layout + } +} + +impl<'a, 'b, 'tcx> HasTyCtxt<'tcx> for &'a ConstPropagator<'a, 'b, 'tcx> { + #[inline] + fn tcx<'c>(&'c self) -> TyCtxt<'c, 'tcx, 'tcx> { + self.tcx + } +} + impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { fn new( mir: &'b Mir<'tcx>, @@ -134,15 +169,43 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } } + fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> { + match *place { + Place::Local(loc) => self.places[loc].clone(), + Place::Projection(ref proj) => match proj.elem { + ProjectionElem::Field(field, _) => { + trace!("field proj on {:?}", proj.base); + let (base, ty, span) = self.eval_place(&proj.base)?; + match base { + Value::ByValPair(a, b) => { + trace!("by val pair: {:?}, {:?}", a, b); + let base_layout = self.tcx.layout_of(self.param_env.and(ty)).ok()?; + trace!("layout computed"); + use rustc_data_structures::indexed_vec::Idx; + let field_index = field.index(); + let val = if field_index == 0 { + a + } else { + assert_eq!(field_index, 1); + b + }; + let field = base_layout.field(&*self, field_index).ok()?; + trace!("projection resulted in: {:?}", val); + Some((Value::ByVal(val), field.ty, span)) + }, + _ => None, + } + }, + _ => None, + }, + _ => None, + } + } + fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> { match *op { Operand::Constant(ref c) => self.eval_constant(c), - Operand::Move(ref place) | Operand::Copy(ref place) => match *place { - Place::Local(loc) => self.places[loc].clone(), - // FIXME(oli-obk): field and index projections - Place::Projection(_) => None, - _ => None, - }, + Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place), } } @@ -235,18 +298,24 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?; if op == BinOp::Shr || op == BinOp::Shl { let param_env = self.tcx.param_env(self.source.def_id); - let bits = self.tcx.layout_of(param_env.and(place_ty)).unwrap().size.bits(); + let left_ty = left.ty(self.mir, self.tcx); + let bits = self.tcx.layout_of(param_env.and(left_ty)).unwrap().size.bits(); if r.to_bytes().ok().map_or(false, |b| b >= bits as u128) { let scope_info = match self.mir.visibility_scope_info { ClearCrossCrate::Set(ref data) => data, ClearCrossCrate::Clear => return None, }; + let dir = if op == BinOp::Shr { + "right" + } else { + "left" + }; let node_id = scope_info[source_info.scope].lint_root; self.tcx.lint_node( ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, node_id, span, - "bitshift exceeds the type's number of bits"); + &format!("attempt to shift {} with overflow", dir)); return None; } } @@ -334,6 +403,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { Copy | Move | StorageDead | StorageLive | Validate | + Projection(_) | Inspect => {}, _ => self.can_const_prop[local] = false, } @@ -364,6 +434,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { .to_ty(self.tcx); if let Some(value) = self.const_prop(rval, place_ty, statement.source_info) { if let Place::Local(local) = *place { + trace!("checking whether {:?} can be stored to {:?}", value, local); if self.can_const_prop[local] { trace!("storing {:?} to {:?}", value, local); assert!(self.places[local].is_none()); @@ -384,7 +455,22 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { self.super_terminator_kind(block, kind, location); if let TerminatorKind::Assert { expected, msg, cond, .. } = kind { if let Some(value) = self.eval_operand(cond) { + trace!("assertion on {:?} should be {:?}", value, expected); if Value::ByVal(PrimVal::from_bool(*expected)) != value.0 { + // poison all places this operand references so that further code + // doesn't use the invalid value + match cond { + Operand::Move(ref place) | Operand::Copy(ref place) => { + let mut place = place; + while let Place::Projection(ref proj) = *place { + place = &proj.base; + } + if let Place::Local(local) = *place { + self.places[local] = None; + } + }, + Operand::Constant(_) => {} + } let span = self.mir[block] .terminator .as_ref() @@ -396,21 +482,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"); - let mut lint = self.tcx.struct_span_lint_node( - ::rustc::lint::builtin::CONST_ERR, - node_id, - span, - "constant evaluation error", - ); use rustc::mir::AssertMessage::*; - match msg { + let msg = match msg { // Need proper const propagator for these GeneratorResumedAfterReturn | - GeneratorResumedAfterPanic => { - lint.cancel(); - return; - }, - Math(ref err) => lint.span_label(span, err.description()), + GeneratorResumedAfterPanic => return, + Math(ref err) => err.description().to_owned(), BoundsCheck { ref len, ref index } => { let len = self.eval_operand(len).expect("len must be const"); let len = match len.0 { @@ -424,17 +501,20 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { Value::ByVal(PrimVal::Bytes(n)) => n, _ => bug!("const index not primitive: {:?}", index), }; - lint.span_label( - span, - format!( - "index out of bounds: \ - the len is {} but the index is {}", - len, - index, - ), + format!( + "index out of bounds: \ + the len is {} but the index is {}", + len, + index, ) }, - }.emit(); + }; + self.tcx.lint_node( + ::rustc::lint::builtin::CONST_ERR, + node_id, + span, + &msg, + ); } } } diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs index 53077d74ce5..3de0f1ff61e 100644 --- a/src/test/compile-fail/const-err-early.rs +++ b/src/test/compile-fail/const-err-early.rs @@ -11,11 +11,14 @@ #![deny(const_err)] pub const A: i8 = -std::i8::MIN; //~ ERROR E0080 -//~| ERROR const_err -//~| ERROR const_err +//~^ ERROR attempt to negate with overflow +//~| ERROR constant evaluation error pub const B: u8 = 200u8 + 200u8; //~ ERROR E0080 +//~^ ERROR attempt to add with overflow pub const C: u8 = 200u8 * 4; //~ ERROR E0080 +//~^ ERROR attempt to multiply with overflow pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR E0080 +//~^ ERROR attempt to subtract with overflow pub const E: u8 = [5u8][1]; //~^ ERROR E0080 diff --git a/src/test/compile-fail/const-err-multi.rs b/src/test/compile-fail/const-err-multi.rs index d72097848fe..d2355f57f17 100644 --- a/src/test/compile-fail/const-err-multi.rs +++ b/src/test/compile-fail/const-err-multi.rs @@ -12,8 +12,8 @@ pub const A: i8 = -std::i8::MIN; //~^ ERROR E0080 -//~| ERROR const_err -//~| ERROR const_err +//~| ERROR attempt to negate with overflow +//~| ERROR constant evaluation error pub const B: i8 = A; //~^ ERROR E0080 pub const C: u8 = A as u8; diff --git a/src/test/compile-fail/const-err2.rs b/src/test/compile-fail/const-err2.rs index 09983f17926..46b73371e56 100644 --- a/src/test/compile-fail/const-err2.rs +++ b/src/test/compile-fail/const-err2.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// needed because negating int::MIN will behave differently between +// optimized compilation and unoptimized compilation and thus would +// lead to different lints being emitted +// compile-flags: -O + #![feature(rustc_attrs)] #![allow(exceeding_bitshifts)] #![deny(const_err)] diff --git a/src/test/compile-fail/const-eval-overflow2.rs b/src/test/compile-fail/const-eval-overflow2.rs index 25787b7bb4b..a0d8f9672c0 100644 --- a/src/test/compile-fail/const-eval-overflow2.rs +++ b/src/test/compile-fail/const-eval-overflow2.rs @@ -25,46 +25,54 @@ const VALS_I8: (i8,) = ( i8::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_I16: (i16,) = ( i16::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_I32: (i32,) = ( i32::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_I64: (i64,) = ( i64::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_U8: (u8,) = ( u8::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_U16: (u16,) = ( u16::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_U32: (u32,) = ( u32::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); const VALS_U64: (u64,) = ( u64::MIN - 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to subtract with overflow ); fn main() { diff --git a/src/test/compile-fail/const-eval-overflow2b.rs b/src/test/compile-fail/const-eval-overflow2b.rs index d8332757b64..08128f90e53 100644 --- a/src/test/compile-fail/const-eval-overflow2b.rs +++ b/src/test/compile-fail/const-eval-overflow2b.rs @@ -25,46 +25,54 @@ const VALS_I8: (i8,) = ( i8::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_I16: (i16,) = ( i16::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_I32: (i32,) = ( i32::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_I64: (i64,) = ( i64::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_U8: (u8,) = ( u8::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_U16: (u16,) = ( u16::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_U32: (u32,) = ( u32::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); const VALS_U64: (u64,) = ( u64::MAX + 1, //~^ ERROR constant evaluation error + //~| ERROR attempt to add with overflow ); fn main() { diff --git a/src/test/compile-fail/const-eval-overflow2c.rs b/src/test/compile-fail/const-eval-overflow2c.rs index 2a8e4dc2c34..31a1638cade 100644 --- a/src/test/compile-fail/const-eval-overflow2c.rs +++ b/src/test/compile-fail/const-eval-overflow2c.rs @@ -25,46 +25,54 @@ const VALS_I8: (i8,) = ( i8::MIN * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_I16: (i16,) = ( i16::MIN * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_I32: (i32,) = ( i32::MIN * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_I64: (i64,) = ( i64::MIN * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_U8: (u8,) = ( u8::MAX * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_U16: (u16,) = ( u16::MAX * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_U32: (u32,) = ( u32::MAX * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); const VALS_U64: (u64,) = ( u64::MAX * 2, //~^ ERROR constant evaluation error + //~| ERROR attempt to multiply with overflow ); fn main() { diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs index 469618407d8..49f76c532df 100644 --- a/src/test/compile-fail/eval-enum.rs +++ b/src/test/compile-fail/eval-enum.rs @@ -13,12 +13,10 @@ enum Test { //~^ attempt to divide by zero //~| ERROR constant evaluation error //~| WARN constant evaluation error - //~| WARN constant evaluation error RemZero = 1%0, //~^ attempt to calculate the remainder with a divisor of zero //~| ERROR constant evaluation error //~| WARN constant evaluation error - //~| WARN constant evaluation error } fn main() {} diff --git a/src/test/compile-fail/issue-44578.rs b/src/test/compile-fail/issue-44578.rs index 9efe3d90a93..18cfb35113d 100644 --- a/src/test/compile-fail/issue-44578.rs +++ b/src/test/compile-fail/issue-44578.rs @@ -18,7 +18,7 @@ enum Bar<A, B> { } impl<A: Foo, B: Foo> Foo for Bar<A, B> { - const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; //~ E0080 + const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; } impl Foo for u8 { diff --git a/src/test/compile-fail/issue-8460-const.rs b/src/test/compile-fail/issue-8460-const.rs index 024aca2e66d..1d59e75a0f0 100644 --- a/src/test/compile-fail/issue-8460-const.rs +++ b/src/test/compile-fail/issue-8460-const.rs @@ -9,110 +9,69 @@ // except according to those terms. #![deny(const_err)] -//~^ NOTE lint level defined here use std::{isize, i8, i16, i32, i64}; use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - //~^ NOTE attempt to divide with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - //~^ NOTE attempt to divide with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - //~^ NOTE attempt to divide with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - //~^ NOTE attempt to divide with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - //~^ NOTE attempt to divide with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - //~^ NOTE attempt to divide by zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide by zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - //~^ NOTE attempt to divide by zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide by zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - //~^ NOTE attempt to divide by zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide by zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - //~^ NOTE attempt to divide by zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide by zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - //~^ NOTE attempt to divide by zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to divide by zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with overflow - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with overflow //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with a divisor of zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with a divisor of zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with a divisor of zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with a divisor of zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR constant evaluation error assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - //~^ NOTE attempt to calculate the remainder with a divisor of zero - //~| NOTE attempted to do overflowing math - //~| ERROR constant evaluation error + //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR constant evaluation error } diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs index 34b43c5badb..5ebfcc4926b 100644 --- a/src/test/compile-fail/lint-exceeding-bitshifts.rs +++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs @@ -8,50 +8,50 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(exceeding_bitshifts)] +#![deny(exceeding_bitshifts, const_err)] #![allow(unused_variables)] -#![allow(dead_code, const_err)] +#![allow(dead_code)] fn main() { let n = 1u8 << 7; - let n = 1u8 << 8; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u8 << 8; //~ ERROR: attempt to shift left with overflow let n = 1u16 << 15; - let n = 1u16 << 16; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u16 << 16; //~ ERROR: attempt to shift left with overflow let n = 1u32 << 31; - let n = 1u32 << 32; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u32 << 32; //~ ERROR: attempt to shift left with overflow let n = 1u64 << 63; - let n = 1u64 << 64; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u64 << 64; //~ ERROR: attempt to shift left with overflow let n = 1i8 << 7; - let n = 1i8 << 8; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i8 << 8; //~ ERROR: attempt to shift left with overflow let n = 1i16 << 15; - let n = 1i16 << 16; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i16 << 16; //~ ERROR: attempt to shift left with overflow let n = 1i32 << 31; - let n = 1i32 << 32; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i32 << 32; //~ ERROR: attempt to shift left with overflow let n = 1i64 << 63; - let n = 1i64 << 64; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i64 << 64; //~ ERROR: attempt to shift left with overflow let n = 1u8 >> 7; - let n = 1u8 >> 8; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u8 >> 8; //~ ERROR: attempt to shift right with overflow let n = 1u16 >> 15; - let n = 1u16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u16 >> 16; //~ ERROR: attempt to shift right with overflow let n = 1u32 >> 31; - let n = 1u32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u32 >> 32; //~ ERROR: attempt to shift right with overflow let n = 1u64 >> 63; - let n = 1u64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u64 >> 64; //~ ERROR: attempt to shift right with overflow let n = 1i8 >> 7; - let n = 1i8 >> 8; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i8 >> 8; //~ ERROR: attempt to shift right with overflow let n = 1i16 >> 15; - let n = 1i16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i16 >> 16; //~ ERROR: attempt to shift right with overflow let n = 1i32 >> 31; - let n = 1i32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i32 >> 32; //~ ERROR: attempt to shift right with overflow let n = 1i64 >> 63; - let n = 1i64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1i64 >> 64; //~ ERROR: attempt 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 = n << 8; //~ ERROR: attempt to shift left with overflow - let n = 1u8 << -8; //~ ERROR: bitshift exceeds the type's number of bits + let n = 1u8 << -8; //~ ERROR: attempt to shift left with overflow let n = 1i8<<(1isize+-1); } diff --git a/src/test/compile-fail/lint-exceeding-bitshifts2.rs b/src/test/compile-fail/lint-exceeding-bitshifts2.rs index a8027034fbe..3ba300eb7c4 100644 --- a/src/test/compile-fail/lint-exceeding-bitshifts2.rs +++ b/src/test/compile-fail/lint-exceeding-bitshifts2.rs @@ -14,7 +14,7 @@ fn main() { let n = 1u8 << (4+3); - let n = 1u8 << (4+4); //~ ERROR: bitshift exceeds + let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow let n = 1i64 >> [63][0]; let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation @@ -22,6 +22,6 @@ fn main() { const BITS: usize = 32; #[cfg(target_pointer_width = "64")] const BITS: usize = 64; - let n = 1_isize << BITS; //~ ERROR: bitshift exceeds - let n = 1_usize << BITS; //~ ERROR: bitshift exceeds + let n = 1_isize << BITS; //~ ERROR: attempt to shift left with overflow + let n = 1_usize << BITS; //~ ERROR: attempt to shift left with overflow } diff --git a/src/test/ui/const-eval-overflow-4.rs b/src/test/ui/const-eval-overflow-4.rs index a1b90f623cd..24e178152ee 100644 --- a/src/test/ui/const-eval-overflow-4.rs +++ b/src/test/ui/const-eval-overflow-4.rs @@ -22,6 +22,7 @@ use std::{u8, u16, u32, u64, usize}; const A_I8_T : [u32; (i8::MAX as i8 + 1i8) as usize] //~^ ERROR E0080 + //~| WARN attempt to add with overflow = [0; (i8::MAX as usize) + 1]; fn main() { diff --git a/src/test/ui/const-eval-overflow-4.stderr b/src/test/ui/const-eval-overflow-4.stderr index e967f024ae3..14753038fef 100644 --- a/src/test/ui/const-eval-overflow-4.stderr +++ b/src/test/ui/const-eval-overflow-4.stderr @@ -1,3 +1,11 @@ +warning: attempt to add with overflow + --> $DIR/const-eval-overflow-4.rs:23:13 + | +LL | : [u32; (i8::MAX as i8 + 1i8) as usize] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(const_err)] on by default + error[E0080]: constant evaluation error --> $DIR/const-eval-overflow-4.rs:23:13 | diff --git a/src/test/ui/const-eval/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs index 41ceb609df5..324bcf60e8f 100644 --- a/src/test/ui/const-eval/conditional_array_execution.rs +++ b/src/test/ui/const-eval/conditional_array_execution.rs @@ -10,7 +10,8 @@ const X: u32 = 5; const Y: u32 = 6; -const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~ E0080 +const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; +//~^ WARN attempt to subtract with overflow fn main() { println!("{}", FOO); //~ E0080 diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index 8d421f401ca..4cf12e22283 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -1,15 +1,17 @@ -error[E0080]: constant evaluation error - --> $DIR/conditional_array_execution.rs:16:20 +warning: attempt to subtract with overflow + --> $DIR/conditional_array_execution.rs:13:19 | -LL | println!("{}", FOO); //~ E0080 - | ^^^ referenced constant has errors +LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; + | ^^^^^ + | + = note: #[warn(const_err)] on by default error[E0080]: constant evaluation error - --> $DIR/conditional_array_execution.rs:13:19 + --> $DIR/conditional_array_execution.rs:17:20 | -LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~ E0080 - | ^^^^^ attempt to subtract with overflow +LL | println!("{}", FOO); //~ E0080 + | ^^^ referenced constant has errors -error: aborting due to 2 previous errors +error: aborting due to previous error If you want more information on this error, try using "rustc --explain E0080" diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs index e87b2caa49f..d5c4796d0b4 100644 --- a/src/test/ui/const-eval/issue-43197.rs +++ b/src/test/ui/const-eval/issue-43197.rs @@ -15,8 +15,10 @@ const fn foo(x: u32) -> u32 { } fn main() { - const X: u32 = 0-1; //~ ERROR constant evaluation error - const Y: u32 = foo(0-1); //~ ERROR constant evaluation error + const X: u32 = 0-1; + //~^ WARN attempt to subtract with overflow + const Y: u32 = foo(0-1); + //~^ WARN attempt to subtract with overflow println!("{} {}", X, Y); //~^ ERROR constant evaluation error //~| ERROR constant evaluation error diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index 21b9a282c48..3f108268747 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -1,27 +1,29 @@ -error[E0080]: constant evaluation error - --> $DIR/issue-43197.rs:20:23 +warning: attempt to subtract with overflow + --> $DIR/issue-43197.rs:18:20 | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors +LL | const X: u32 = 0-1; + | ^^^ + | + = note: #[warn(const_err)] on by default error[E0080]: constant evaluation error - --> $DIR/issue-43197.rs:20:26 + --> $DIR/issue-43197.rs:22:23 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors -error[E0080]: constant evaluation error - --> $DIR/issue-43197.rs:19:24 +warning: attempt to subtract with overflow + --> $DIR/issue-43197.rs:20:24 | -LL | const Y: u32 = foo(0-1); //~ ERROR constant evaluation error - | ^^^ attempt to subtract with overflow +LL | const Y: u32 = foo(0-1); + | ^^^ error[E0080]: constant evaluation error - --> $DIR/issue-43197.rs:18:20 + --> $DIR/issue-43197.rs:22:26 | -LL | const X: u32 = 0-1; //~ ERROR constant evaluation error - | ^^^ attempt to subtract with overflow +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors If you want more information on this error, try using "rustc --explain E0080" diff --git a/src/test/ui/const-eval/pub_const_err.rs b/src/test/ui/const-eval/pub_const_err.rs new file mode 100644 index 00000000000..bdb9f5b19a8 --- /dev/null +++ b/src/test/ui/const-eval/pub_const_err.rs @@ -0,0 +1,16 @@ +// 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. + +#![deny(const_err)] + +#![crate_type = "lib"] + +pub const Z: u32 = 0 - 1; +//~^ ERROR attempt to subtract with overflow diff --git a/src/test/ui/const-eval/pub_const_err.stderr b/src/test/ui/const-eval/pub_const_err.stderr new file mode 100644 index 00000000000..b77ec38ca16 --- /dev/null +++ b/src/test/ui/const-eval/pub_const_err.stderr @@ -0,0 +1,14 @@ +error: attempt to subtract with overflow + --> $DIR/pub_const_err.rs:15:20 + | +LL | pub const Z: u32 = 0 - 1; + | ^^^^^ + | +note: lint level defined here + --> $DIR/pub_const_err.rs:11:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-len-underflow-separate-spans.rs b/src/test/ui/const-len-underflow-separate-spans.rs index 35e3ba9ce09..ee07dabab1f 100644 --- a/src/test/ui/const-len-underflow-separate-spans.rs +++ b/src/test/ui/const-len-underflow-separate-spans.rs @@ -16,6 +16,7 @@ const ONE: usize = 1; const TWO: usize = 2; const LEN: usize = ONE - TWO; //~^ ERROR E0080 +//~| WARN attempt to subtract with overflow fn main() { let a: [i8; LEN] = unimplemented!(); diff --git a/src/test/ui/const-len-underflow-separate-spans.stderr b/src/test/ui/const-len-underflow-separate-spans.stderr index 301b063885c..98f4ac9e83f 100644 --- a/src/test/ui/const-len-underflow-separate-spans.stderr +++ b/src/test/ui/const-len-underflow-separate-spans.stderr @@ -1,3 +1,11 @@ +warning: attempt to subtract with overflow + --> $DIR/const-len-underflow-separate-spans.rs:17:20 + | +LL | const LEN: usize = ONE - TWO; + | ^^^^^^^^^ + | + = note: #[warn(const_err)] on by default + error[E0080]: constant evaluation error --> $DIR/const-len-underflow-separate-spans.rs:17:20 | @@ -5,7 +13,7 @@ LL | const LEN: usize = ONE - TWO; | ^^^^^^^^^ attempt to subtract with overflow error[E0080]: constant evaluation error - --> $DIR/const-len-underflow-separate-spans.rs:21:17 + --> $DIR/const-len-underflow-separate-spans.rs:22:17 | LL | let a: [i8; LEN] = unimplemented!(); | ^^^ referenced constant has errors diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs index cca63f23b77..c8e42571128 100644 --- a/src/test/ui/error-codes/E0080.rs +++ b/src/test/ui/error-codes/E0080.rs @@ -10,7 +10,6 @@ enum Enum { X = (1 << 500), //~ ERROR E0080 - //~| ERROR bitshift exceeds //~| shift left with overflow Y = (1 / 0) //~ ERROR E0080 //~| const_err diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr index 501051b9fe6..6db53acd6b9 100644 --- a/src/test/ui/error-codes/E0080.stderr +++ b/src/test/ui/error-codes/E0080.stderr @@ -1,4 +1,4 @@ -error: bitshift exceeds the type's number of bits +error: attempt to shift left with overflow --> $DIR/E0080.rs:12:9 | LL | X = (1 << 500), //~ ERROR E0080 @@ -12,22 +12,22 @@ error[E0080]: constant evaluation error LL | X = (1 << 500), //~ ERROR E0080 | ^^^^^^^^^^ attempt to shift left with overflow -warning: constant evaluation error - --> $DIR/E0080.rs:15:9 +warning: attempt to divide by zero + --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 - | ^^^^^^^ attempt to divide by zero + | ^^^^^^^ | = note: #[warn(const_err)] on by default warning: constant evaluation error - --> $DIR/E0080.rs:15:9 + --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 | ^^^^^^^ attempted to do overflowing math error[E0080]: constant evaluation error - --> $DIR/E0080.rs:15:9 + --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 | ^^^^^^^ attempt to divide by zero |
