Auto merge of #71518 - felix91gr:const_prop_bugfix_just_block_prop, r=wesleywiser
Const-prop bugfix: only add propagation inside own block for user variables A testing spinoff of #71298. This one only adds the const-prop for locals that are user variables.
This commit is contained in:
commit
92019986aa
@ -274,6 +274,8 @@ struct ConstPropagator<'mir, 'tcx> {
|
||||
// Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
|
||||
// the last known `SourceInfo` here and just keep revisiting it.
|
||||
source_info: Option<SourceInfo>,
|
||||
// Locals we need to forget at the end of the current block
|
||||
locals_of_current_block: BitSet<Local>,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> {
|
||||
@ -343,6 +345,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
|
||||
local_decls: body.local_decls.clone(),
|
||||
source_info: None,
|
||||
locals_of_current_block: BitSet::new_empty(body.local_decls.len()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,8 +360,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_const(&mut self, local: Local) {
|
||||
self.ecx.frame_mut().locals[local] =
|
||||
/// Remove `local` from the pool of `Locals`. Allows writing to them,
|
||||
/// but not reading from them anymore.
|
||||
fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) {
|
||||
ecx.frame_mut().locals[local] =
|
||||
LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
|
||||
}
|
||||
|
||||
@ -389,6 +394,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value, if any, of evaluating `c`.
|
||||
fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
|
||||
// FIXME we need to revisit this for #67176
|
||||
if c.needs_subst() {
|
||||
@ -429,11 +435,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value, if any, of evaluating `place`.
|
||||
fn eval_place(&mut self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
|
||||
trace!("eval_place(place={:?})", place);
|
||||
self.use_ecx(|this| this.ecx.eval_place_to_op(place, None))
|
||||
}
|
||||
|
||||
/// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
|
||||
/// or `eval_place`, depending on the variant of `Operand` used.
|
||||
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
|
||||
match *op {
|
||||
Operand::Constant(ref c) => self.eval_constant(c, source_info),
|
||||
@ -592,6 +601,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `Operand::Constant` from a `Scalar` value
|
||||
fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Operand<'tcx> {
|
||||
Operand::Constant(Box::new(Constant {
|
||||
span,
|
||||
@ -637,6 +647,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
// Found a value represented as a pair. For now only do cont-prop if type of
|
||||
// Rvalue is also a pair with two scalars. The more general case is more
|
||||
// complicated to implement so we'll do it later.
|
||||
// FIXME: implement the general case stated above ^.
|
||||
let ty = &value.layout.ty.kind;
|
||||
// Only do it for tuples
|
||||
if let ty::Tuple(substs) = ty {
|
||||
@ -673,6 +684,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if and only if this `op` should be const-propagated into.
|
||||
fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool {
|
||||
let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level;
|
||||
|
||||
@ -704,6 +716,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
enum ConstPropMode {
|
||||
/// The `Local` can be propagated into and reads of this `Local` can also be propagated.
|
||||
FullConstProp,
|
||||
/// The `Local` can only be propagated into and from its own block.
|
||||
OnlyInsideOwnBlock,
|
||||
/// The `Local` can be propagated into but reads cannot be propagated.
|
||||
OnlyPropagateInto,
|
||||
/// No propagation is allowed at all.
|
||||
@ -712,28 +726,41 @@ enum ConstPropMode {
|
||||
|
||||
struct CanConstProp {
|
||||
can_const_prop: IndexVec<Local, ConstPropMode>,
|
||||
// false at the beginning, once set, there are not allowed to be any more assignments
|
||||
// False at the beginning. Once set, no more assignments are allowed to that local.
|
||||
found_assignment: BitSet<Local>,
|
||||
// Cache of locals' information
|
||||
local_kinds: IndexVec<Local, LocalKind>,
|
||||
}
|
||||
|
||||
impl CanConstProp {
|
||||
/// returns true if `local` can be propagated
|
||||
/// Returns true if `local` can be propagated
|
||||
fn check(body: &Body<'_>) -> IndexVec<Local, ConstPropMode> {
|
||||
let mut cpv = CanConstProp {
|
||||
can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp, &body.local_decls),
|
||||
found_assignment: BitSet::new_empty(body.local_decls.len()),
|
||||
local_kinds: IndexVec::from_fn_n(
|
||||
|local| body.local_kind(local),
|
||||
body.local_decls.len(),
|
||||
),
|
||||
};
|
||||
for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
|
||||
// cannot use args at all
|
||||
// cannot use locals because if x < y { y - x } else { x - y } would
|
||||
// Cannot use args at all
|
||||
// Cannot use locals because if x < y { y - x } else { x - y } would
|
||||
// lint for x != y
|
||||
// FIXME(oli-obk): lint variables until they are used in a condition
|
||||
// FIXME(oli-obk): lint if return value is constant
|
||||
let local_kind = body.local_kind(local);
|
||||
|
||||
if local_kind == LocalKind::Arg || local_kind == LocalKind::Var {
|
||||
if cpv.local_kinds[local] == LocalKind::Arg {
|
||||
*val = ConstPropMode::OnlyPropagateInto;
|
||||
trace!("local {:?} can't be const propagated because it's not a temporary", local);
|
||||
trace!(
|
||||
"local {:?} can't be const propagated because it's a function argument",
|
||||
local
|
||||
);
|
||||
} else if cpv.local_kinds[local] == LocalKind::Var {
|
||||
*val = ConstPropMode::OnlyInsideOwnBlock;
|
||||
trace!(
|
||||
"local {:?} will only be propagated inside its block, because it's a user variable",
|
||||
local
|
||||
);
|
||||
}
|
||||
}
|
||||
cpv.visit_body(&body);
|
||||
@ -759,8 +786,12 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
|
||||
| NonMutatingUse(NonMutatingUseContext::Move)
|
||||
| NonMutatingUse(NonMutatingUseContext::Inspect)
|
||||
| NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
| MutatingUse(MutatingUseContext::Projection)
|
||||
| NonUse(_) => {}
|
||||
MutatingUse(MutatingUseContext::Projection) => {
|
||||
if self.local_kinds[local] != LocalKind::Temp {
|
||||
self.can_const_prop[local] = ConstPropMode::NoPropagation;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
|
||||
self.can_const_prop[local] = ConstPropMode::NoPropagation;
|
||||
@ -797,25 +828,35 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||
if let Some(local) = place.as_local() {
|
||||
let can_const_prop = self.can_const_prop[local];
|
||||
if let Some(()) = self.const_prop(rval, place_layout, source_info, place) {
|
||||
if can_const_prop == ConstPropMode::FullConstProp
|
||||
|| can_const_prop == ConstPropMode::OnlyPropagateInto
|
||||
{
|
||||
if can_const_prop != ConstPropMode::NoPropagation {
|
||||
// This will return None for Locals that are from other blocks,
|
||||
// so it should be okay to propagate from here on down.
|
||||
if let Some(value) = self.get_const(local) {
|
||||
if self.should_const_prop(value) {
|
||||
trace!("replacing {:?} with {:?}", rval, value);
|
||||
self.replace_with_const(rval, value, statement.source_info);
|
||||
|
||||
if can_const_prop == ConstPropMode::FullConstProp {
|
||||
if can_const_prop == ConstPropMode::FullConstProp
|
||||
|| can_const_prop == ConstPropMode::OnlyInsideOwnBlock
|
||||
{
|
||||
trace!("propagated into {:?}", local);
|
||||
}
|
||||
}
|
||||
if can_const_prop == ConstPropMode::OnlyInsideOwnBlock {
|
||||
trace!(
|
||||
"found local restricted to its block. Will remove it from const-prop after block is finished. Local: {:?}",
|
||||
local
|
||||
);
|
||||
self.locals_of_current_block.insert(local);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.can_const_prop[local] != ConstPropMode::FullConstProp {
|
||||
if self.can_const_prop[local] == ConstPropMode::OnlyPropagateInto
|
||||
|| self.can_const_prop[local] == ConstPropMode::NoPropagation
|
||||
{
|
||||
trace!("can't propagate into {:?}", local);
|
||||
if local != RETURN_PLACE {
|
||||
self.remove_const(local);
|
||||
Self::remove_const(&mut self.ecx, local);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -850,11 +891,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||
let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
|
||||
let value_const = self.ecx.read_scalar(value).unwrap();
|
||||
if expected != value_const {
|
||||
// poison all places this operand references so that further code
|
||||
// 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) => {
|
||||
self.remove_const(place.local);
|
||||
Self::remove_const(&mut self.ecx, place.local);
|
||||
}
|
||||
Operand::Constant(_) => {}
|
||||
}
|
||||
@ -916,7 +957,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
//none of these have Operands to const-propagate
|
||||
// None of these have Operands to const-propagate
|
||||
TerminatorKind::Goto { .. }
|
||||
| TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
@ -931,5 +972,13 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||
//FIXME(wesleywiser) Call does have Operands that could be const-propagated
|
||||
TerminatorKind::Call { .. } => {}
|
||||
}
|
||||
// We remove all Locals which are restricted in propagation to their containing blocks.
|
||||
// We wouldn't need to clone, but the borrow checker can't see that we're not aliasing
|
||||
// the locals_of_current_block field, so we need to clone it first.
|
||||
// let ecx = &mut self.ecx;
|
||||
for local in self.locals_of_current_block.iter() {
|
||||
Self::remove_const(&mut self.ecx, local);
|
||||
}
|
||||
self.locals_of_current_block.clear();
|
||||
}
|
||||
}
|
||||
|
6
src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
Normal file
6
src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
let y = 0;
|
||||
let _z = 1 / y;
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 3:11
|
||||
let _1: i32; // in scope 0 at $DIR/bad_op_div_by_zero.rs:4:9: 4:10
|
||||
let mut _3: i32; // in scope 0 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
|
||||
let mut _4: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
let mut _5: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
let mut _6: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
let mut _7: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
scope 1 {
|
||||
debug y => _1; // in scope 1 at $DIR/bad_op_div_by_zero.rs:4:9: 4:10
|
||||
let _2: i32; // in scope 1 at $DIR/bad_op_div_by_zero.rs:5:9: 5:11
|
||||
scope 2 {
|
||||
debug _z => _2; // in scope 2 at $DIR/bad_op_div_by_zero.rs:5:9: 5:11
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:4:9: 4:10
|
||||
_1 = const 0i32; // scope 0 at $DIR/bad_op_div_by_zero.rs:4:13: 4:14
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_div_by_zero.rs:4:13: 4:14
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
|
||||
StorageLive(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:9: 5:11
|
||||
StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
|
||||
- _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
|
||||
- _4 = Eq(_3, const 0i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ _3 = const 0i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // + span: $DIR/bad_op_div_by_zero.rs:5:18: 5:19
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
|
||||
+ _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x01))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
assert(!move _4, "attempt to divide by zero") -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _5 = Eq(_3, const -1i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ _5 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
- // + ty: i32
|
||||
- // + val: Value(Scalar(0xffffffff))
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
- // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) }
|
||||
- _6 = Eq(const 1i32, const std::i32::MIN); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ _6 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
- // + ty: i32
|
||||
- // + val: Value(Scalar(0x00000001))
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15
|
||||
- // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
|
||||
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ _7 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
- // + ty: i32
|
||||
- // + val: Value(Scalar(0x80000000))
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
- // + literal: Const { ty: i32, val: Value(Scalar(0x80000000)) }
|
||||
- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
- assert(!move _7, "attempt to divide with overflow") -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ assert(!const false, "attempt to divide with overflow") -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_2 = Div(const 1i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000001))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
|
||||
StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
|
||||
_0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 6:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_div_by_zero.rs:3:11: 6:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:6:1: 6:2
|
||||
StorageDead(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:6:1: 6:2
|
||||
return; // scope 0 at $DIR/bad_op_div_by_zero.rs:6:2: 6:2
|
||||
}
|
||||
}
|
||||
|
6
src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs
Normal file
6
src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
let y = 0;
|
||||
let _z = 1 % y;
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/bad_op_mod_by_zero.rs:3:11: 3:11
|
||||
let _1: i32; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:4:9: 4:10
|
||||
let mut _3: i32; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
|
||||
let mut _4: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
let mut _5: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
let mut _6: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
let mut _7: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
scope 1 {
|
||||
debug y => _1; // in scope 1 at $DIR/bad_op_mod_by_zero.rs:4:9: 4:10
|
||||
let _2: i32; // in scope 1 at $DIR/bad_op_mod_by_zero.rs:5:9: 5:11
|
||||
scope 2 {
|
||||
debug _z => _2; // in scope 2 at $DIR/bad_op_mod_by_zero.rs:5:9: 5:11
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:4:9: 4:10
|
||||
_1 = const 0i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:4:13: 4:14
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_mod_by_zero.rs:4:13: 4:14
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
|
||||
StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:9: 5:11
|
||||
StorageLive(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
|
||||
- _3 = _1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
|
||||
- _4 = Eq(_3, const 0i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ _3 = const 0i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // + span: $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
|
||||
+ _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x01))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
assert(!move _4, "attempt to calculate the remainder with a divisor of zero") -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _5 = Eq(_3, const -1i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
- // + ty: i32
|
||||
- // + val: Value(Scalar(0xffffffff))
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
- // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) }
|
||||
- _6 = Eq(const 1i32, const std::i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
- // + ty: i32
|
||||
- // + val: Value(Scalar(0x00000001))
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:15
|
||||
- // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
|
||||
+ // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
- // + ty: i32
|
||||
- // + val: Value(Scalar(0x80000000))
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
- // + literal: Const { ty: i32, val: Value(Scalar(0x80000000)) }
|
||||
- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
- assert(!move _7, "attempt to calculate the remainder with overflow") -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ assert(!const false, "attempt to calculate the remainder with overflow") -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_2 = Rem(const 1i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000001))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:15
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
|
||||
StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
|
||||
_0 = const (); // scope 0 at $DIR/bad_op_mod_by_zero.rs:3:11: 6:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_mod_by_zero.rs:3:11: 6:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:6:1: 6:2
|
||||
StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:6:1: 6:2
|
||||
return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:6:2: 6:2
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
let a: *const [_] = &[1, 2, 3];
|
||||
unsafe {
|
||||
let _b = (*a)[3];
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:4:11: 4:11
|
||||
let _1: *const [i32] as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:9: 5:10
|
||||
let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:26: 5:35
|
||||
let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
scope 1 {
|
||||
debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:9: 5:10
|
||||
scope 2 {
|
||||
let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:13: 7:15
|
||||
scope 3 {
|
||||
debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:13: 7:15
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:9: 5:10
|
||||
StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
_9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
// ty::Const
|
||||
// + ty: &[i32; 3]
|
||||
// + val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0]))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
// + literal: Const { ty: &[i32; 3], val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0])) }
|
||||
_3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
_2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:34: 5:35
|
||||
StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:35: 5:36
|
||||
StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:13: 7:15
|
||||
StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
_6 = const 3usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000003))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
|
||||
- _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ _7 = const 3usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // ty::Const
|
||||
+ // + ty: usize
|
||||
+ // + val: Value(Scalar(0x00000003))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
|
||||
+ _8 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:25: 7:26
|
||||
_0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:8:5: 8:6
|
||||
StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:1: 9:2
|
||||
return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:2: 9:2
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:4:11: 4:11
|
||||
let _1: *const [i32] as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:9: 5:10
|
||||
let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:26: 5:35
|
||||
let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
scope 1 {
|
||||
debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:9: 5:10
|
||||
scope 2 {
|
||||
let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:13: 7:15
|
||||
scope 3 {
|
||||
debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:13: 7:15
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:9: 5:10
|
||||
StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
_9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
// ty::Const
|
||||
// + ty: &[i32; 3]
|
||||
// + val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0]))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
// + literal: Const { ty: &[i32; 3], val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0])) }
|
||||
_3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
_2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
|
||||
StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:34: 5:35
|
||||
StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:35: 5:36
|
||||
StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:13: 7:15
|
||||
StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
_6 = const 3usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000003))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
|
||||
- _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ _7 = const 3usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // ty::Const
|
||||
+ // + ty: usize
|
||||
+ // + val: Value(Scalar(0x0000000000000003))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
|
||||
+ _8 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
|
||||
StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:25: 7:26
|
||||
_0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:8:5: 8:6
|
||||
StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:1: 9:2
|
||||
return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:2: 9:2
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
fn main() {
|
||||
let x = 1;
|
||||
consume(x);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn consume(_: u32) { }
|
@ -0,0 +1,55 @@
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/scalar_literal_propagation.rs:2:11: 2:11
|
||||
let _1: u32; // in scope 0 at $DIR/scalar_literal_propagation.rs:3:9: 3:10
|
||||
let _2: (); // in scope 0 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
|
||||
let mut _3: u32; // in scope 0 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
|
||||
scope 1 {
|
||||
debug x => _1; // in scope 1 at $DIR/scalar_literal_propagation.rs:3:9: 3:10
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:3:9: 3:10
|
||||
_1 = const 1u32; // scope 0 at $DIR/scalar_literal_propagation.rs:3:13: 3:14
|
||||
// ty::Const
|
||||
// + ty: u32
|
||||
// + val: Value(Scalar(0x00000001))
|
||||
// mir::Constant
|
||||
// + span: $DIR/scalar_literal_propagation.rs:3:13: 3:14
|
||||
// + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) }
|
||||
StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
|
||||
StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
|
||||
- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
|
||||
+ _3 = const 1u32; // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
|
||||
+ // ty::Const
|
||||
+ // + ty: u32
|
||||
+ // + val: Value(Scalar(0x00000001))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/scalar_literal_propagation.rs:4:13: 4:14
|
||||
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) }
|
||||
_2 = const consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
|
||||
// ty::Const
|
||||
// + ty: fn(u32) {consume}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12
|
||||
// + literal: Const { ty: fn(u32) {consume}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:4:14: 4:15
|
||||
StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:4:15: 4:16
|
||||
_0 = const (); // scope 0 at $DIR/scalar_literal_propagation.rs:2:11: 5:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/scalar_literal_propagation.rs:2:11: 5:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:5:1: 5:2
|
||||
return; // scope 0 at $DIR/scalar_literal_propagation.rs:5:2: 5:2
|
||||
}
|
||||
}
|
||||
|
9
src/test/mir-opt/const_prop/tuple_literal_propagation.rs
Normal file
9
src/test/mir-opt/const_prop/tuple_literal_propagation.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
fn main() {
|
||||
let x = (1, 2);
|
||||
|
||||
consume(x);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn consume(_: (u32, u32)) { }
|
@ -0,0 +1,69 @@
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/tuple_literal_propagation.rs:2:11: 2:11
|
||||
let _1: (u32, u32); // in scope 0 at $DIR/tuple_literal_propagation.rs:3:9: 3:10
|
||||
let _2: (); // in scope 0 at $DIR/tuple_literal_propagation.rs:5:5: 5:15
|
||||
let mut _3: (u32, u32); // in scope 0 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
scope 1 {
|
||||
debug x => _1; // in scope 1 at $DIR/tuple_literal_propagation.rs:3:9: 3:10
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:3:9: 3:10
|
||||
_1 = (const 1u32, const 2u32); // scope 0 at $DIR/tuple_literal_propagation.rs:3:13: 3:19
|
||||
// ty::Const
|
||||
// + ty: u32
|
||||
// + val: Value(Scalar(0x00000001))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/tuple_literal_propagation.rs:3:14: 3:15
|
||||
+ // + span: $DIR/tuple_literal_propagation.rs:3:13: 3:19
|
||||
// + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) }
|
||||
// ty::Const
|
||||
// + ty: u32
|
||||
// + val: Value(Scalar(0x00000002))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/tuple_literal_propagation.rs:3:17: 3:18
|
||||
+ // + span: $DIR/tuple_literal_propagation.rs:3:13: 3:19
|
||||
// + literal: Const { ty: u32, val: Value(Scalar(0x00000002)) }
|
||||
StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15
|
||||
StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ _3 = (const 1u32, const 2u32); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ // ty::Const
|
||||
+ // + ty: u32
|
||||
+ // + val: Value(Scalar(0x00000001))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) }
|
||||
+ // ty::Const
|
||||
+ // + ty: u32
|
||||
+ // + val: Value(Scalar(0x00000002))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000002)) }
|
||||
_2 = const consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15
|
||||
// ty::Const
|
||||
// + ty: fn((u32, u32)) {consume}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
|
||||
// + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:5:14: 5:15
|
||||
StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:5:15: 5:16
|
||||
_0 = const (); // scope 0 at $DIR/tuple_literal_propagation.rs:2:11: 6:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/tuple_literal_propagation.rs:2:11: 6:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:6:1: 6:2
|
||||
return; // scope 0 at $DIR/tuple_literal_propagation.rs:6:2: 6:2
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Regression test for issue #66856.
|
||||
//
|
||||
// compile-flags: -Zmir-opt-level=2
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
enum Src {
|
||||
Foo(u8),
|
||||
|
@ -0,0 +1,53 @@
|
||||
- // MIR for `main` before SimplifyArmIdentity
|
||||
+ // MIR for `main` after SimplifyArmIdentity
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:17:11: 17:11
|
||||
let _1: Src as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10
|
||||
let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:19:18: 22:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:20:9: 20:20
|
||||
let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:20:33: 20:34
|
||||
scope 1 {
|
||||
debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:18:9: 18:10
|
||||
let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19
|
||||
scope 2 {
|
||||
}
|
||||
scope 3 {
|
||||
debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:20:18: 20:19
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10
|
||||
((_1 as Foo).0: u8) = const 0u8; // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
|
||||
// ty::Const
|
||||
// + ty: u8
|
||||
// + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-arm-identity.rs:18:27: 18:28
|
||||
// + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
|
||||
discriminant(_1) = 0; // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
|
||||
StorageLive(_2); // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
|
||||
_3 = const 0isize; // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20
|
||||
// ty::Const
|
||||
// + ty: isize
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-arm-identity.rs:20:9: 20:20
|
||||
// + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) }
|
||||
_4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19
|
||||
((_2 as Foo).0: u8) = move _4; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35
|
||||
discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35
|
||||
StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7
|
||||
_0 = const (); // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-arm-identity.rs:17:11: 23:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/simplify-arm-identity.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
- // MIR for `main` before SimplifyArmIdentity
|
||||
+ // MIR for `main` after SimplifyArmIdentity
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:17:11: 17:11
|
||||
let _1: Src as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10
|
||||
let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:19:18: 22:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:20:9: 20:20
|
||||
let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:20:33: 20:34
|
||||
scope 1 {
|
||||
debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:18:9: 18:10
|
||||
let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19
|
||||
scope 2 {
|
||||
}
|
||||
scope 3 {
|
||||
debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:20:18: 20:19
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10
|
||||
((_1 as Foo).0: u8) = const 0u8; // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
|
||||
// ty::Const
|
||||
// + ty: u8
|
||||
// + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-arm-identity.rs:18:27: 18:28
|
||||
// + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
|
||||
discriminant(_1) = 0; // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
|
||||
StorageLive(_2); // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
|
||||
_3 = const 0isize; // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20
|
||||
// ty::Const
|
||||
// + ty: isize
|
||||
// + val: Value(Scalar(0x0000000000000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-arm-identity.rs:20:9: 20:20
|
||||
// + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) }
|
||||
_4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19
|
||||
((_2 as Foo).0: u8) = move _4; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35
|
||||
discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35
|
||||
StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7
|
||||
_0 = const (); // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-arm-identity.rs:17:11: 23:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/simplify-arm-identity.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#[inline(never)]
|
||||
fn noop() {}
|
||||
|
||||
// EMIT_MIR rustc.main.SimplifyBranches-after-copy-prop.diff
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
fn main() {
|
||||
match { let x = false; x } {
|
||||
true => noop(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
- // MIR for `main` before SimplifyBranches-after-copy-prop
|
||||
+ // MIR for `main` after SimplifyBranches-after-copy-prop
|
||||
- // MIR for `main` before ConstProp
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/simplify_match.rs:5:11: 5:11
|
||||
@ -10,19 +10,32 @@
|
||||
}
|
||||
|
||||
bb0: {
|
||||
nop; // scope 0 at $DIR/simplify_match.rs:6:11: 6:31
|
||||
nop; // scope 0 at $DIR/simplify_match.rs:6:17: 6:18
|
||||
nop; // scope 0 at $DIR/simplify_match.rs:6:21: 6:26
|
||||
nop; // scope 1 at $DIR/simplify_match.rs:6:28: 6:29
|
||||
nop; // scope 0 at $DIR/simplify_match.rs:6:30: 6:31
|
||||
- switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:7:9: 7:13
|
||||
- // ty::Const
|
||||
- // + ty: bool
|
||||
- // + val: Value(Scalar(0x00))
|
||||
- // mir::Constant
|
||||
- // + span: $DIR/simplify_match.rs:6:21: 6:26
|
||||
- // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
+ goto -> bb1; // scope 0 at $DIR/simplify_match.rs:7:9: 7:13
|
||||
StorageLive(_1); // scope 0 at $DIR/simplify_match.rs:6:11: 6:31
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_match.rs:6:17: 6:18
|
||||
_2 = const false; // scope 0 at $DIR/simplify_match.rs:6:21: 6:26
|
||||
// ty::Const
|
||||
// + ty: bool
|
||||
// + val: Value(Scalar(0x00))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify_match.rs:6:21: 6:26
|
||||
// + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
- _1 = _2; // scope 1 at $DIR/simplify_match.rs:6:28: 6:29
|
||||
+ _1 = const false; // scope 1 at $DIR/simplify_match.rs:6:28: 6:29
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/simplify_match.rs:6:28: 6:29
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_match.rs:6:30: 6:31
|
||||
- switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:7:9: 7:13
|
||||
+ switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:7:9: 7:13
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x00))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/simplify_match.rs:7:9: 7:13
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
@ -47,7 +60,7 @@
|
||||
}
|
||||
|
||||
bb3: {
|
||||
nop; // scope 0 at $DIR/simplify_match.rs:10:1: 10:2
|
||||
StorageDead(_1); // scope 0 at $DIR/simplify_match.rs:10:1: 10:2
|
||||
return; // scope 0 at $DIR/simplify_match.rs:10:2: 10:2
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// error-pattern:attempt to divide by zero
|
||||
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
let y = 0;
|
||||
let _z = 1 / y;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Test bounds checking for DST raw slices
|
||||
// error-pattern:index out of bounds
|
||||
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
let a: *const [_] = &[1, 2, 3];
|
||||
unsafe {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// error-pattern:attempt to calculate the remainder with a divisor of zero
|
||||
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
let y = 0;
|
||||
let _z = 1 % y;
|
||||
|
24
src/test/ui/mir/mir_detects_invalid_ops.rs
Normal file
24
src/test/ui/mir/mir_detects_invalid_ops.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// build-fail
|
||||
|
||||
fn main() {
|
||||
divide_by_zero();
|
||||
mod_by_zero();
|
||||
oob_error_for_slices();
|
||||
}
|
||||
|
||||
fn divide_by_zero() {
|
||||
let y = 0;
|
||||
let _z = 1 / y; //~ ERROR this operation will panic at runtime [unconditional_panic]
|
||||
}
|
||||
|
||||
fn mod_by_zero() {
|
||||
let y = 0;
|
||||
let _z = 1 % y; //~ ERROR this operation will panic at runtime [unconditional_panic]
|
||||
}
|
||||
|
||||
fn oob_error_for_slices() {
|
||||
let a: *const [_] = &[1, 2, 3];
|
||||
unsafe {
|
||||
let _b = (*a)[3]; //~ ERROR this operation will panic at runtime [unconditional_panic]
|
||||
}
|
||||
}
|
22
src/test/ui/mir/mir_detects_invalid_ops.stderr
Normal file
22
src/test/ui/mir/mir_detects_invalid_ops.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error: this operation will panic at runtime
|
||||
--> $DIR/mir_detects_invalid_ops.rs:11:14
|
||||
|
|
||||
LL | let _z = 1 / y;
|
||||
| ^^^^^ attempt to divide by zero
|
||||
|
|
||||
= note: `#[deny(unconditional_panic)]` on by default
|
||||
|
||||
error: this operation will panic at runtime
|
||||
--> $DIR/mir_detects_invalid_ops.rs:16:14
|
||||
|
|
||||
LL | let _z = 1 % y;
|
||||
| ^^^^^ attempt to calculate the remainder with a divisor of zero
|
||||
|
||||
error: this operation will panic at runtime
|
||||
--> $DIR/mir_detects_invalid_ops.rs:22:18
|
||||
|
|
||||
LL | let _b = (*a)[3];
|
||||
| ^^^^^^^ index out of bounds: the len is 3 but the index is 3
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user