mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Unify the const folding errors
before they differed depending on whether optimizations were on or not
This commit is contained in:
parent
edc5f73433
commit
b5ace9a906
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)]
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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() {}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
@ -1,15 +1,17 @@
|
||||
warning: attempt to subtract with overflow
|
||||
--> $DIR/conditional_array_execution.rs:13:19
|
||||
|
|
||||
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:16:20
|
||||
--> $DIR/conditional_array_execution.rs:17:20
|
||||
|
|
||||
LL | println!("{}", FOO); //~ E0080
|
||||
| ^^^ referenced constant has errors
|
||||
|
||||
error[E0080]: constant evaluation error
|
||||
--> $DIR/conditional_array_execution.rs:13:19
|
||||
|
|
||||
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~ E0080
|
||||
| ^^^^^ attempt to subtract with overflow
|
||||
|
||||
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"
|
||||
|
@ -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
|
||||
|
@ -1,27 +1,29 @@
|
||||
warning: attempt to subtract with overflow
|
||||
--> $DIR/issue-43197.rs:18:20
|
||||
|
|
||||
LL | const X: u32 = 0-1;
|
||||
| ^^^
|
||||
|
|
||||
= note: #[warn(const_err)] on by default
|
||||
|
||||
error[E0080]: constant evaluation error
|
||||
--> $DIR/issue-43197.rs:20:23
|
||||
--> $DIR/issue-43197.rs:22:23
|
||||
|
|
||||
LL | println!("{} {}", X, Y);
|
||||
| ^ referenced constant has errors
|
||||
|
||||
warning: attempt to subtract with overflow
|
||||
--> $DIR/issue-43197.rs:20:24
|
||||
|
|
||||
LL | const Y: u32 = foo(0-1);
|
||||
| ^^^
|
||||
|
||||
error[E0080]: constant evaluation error
|
||||
--> $DIR/issue-43197.rs:20:26
|
||||
--> $DIR/issue-43197.rs:22:26
|
||||
|
|
||||
LL | println!("{} {}", X, Y);
|
||||
| ^ referenced constant has errors
|
||||
|
||||
error[E0080]: constant evaluation error
|
||||
--> $DIR/issue-43197.rs:19:24
|
||||
|
|
||||
LL | const Y: u32 = foo(0-1); //~ ERROR constant evaluation error
|
||||
| ^^^ attempt to subtract with overflow
|
||||
|
||||
error[E0080]: constant evaluation error
|
||||
--> $DIR/issue-43197.rs:18:20
|
||||
|
|
||||
LL | const X: u32 = 0-1; //~ ERROR constant evaluation error
|
||||
| ^^^ attempt to subtract with overflow
|
||||
|
||||
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"
|
||||
|
16
src/test/ui/const-eval/pub_const_err.rs
Normal file
16
src/test/ui/const-eval/pub_const_err.rs
Normal file
@ -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
|
14
src/test/ui/const-eval/pub_const_err.stderr
Normal file
14
src/test/ui/const-eval/pub_const_err.stderr
Normal file
@ -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
|
||||
|
@ -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!();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user