diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a38cf3bba85..09d8f89676a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -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, + // Locals we need to forget at the end of the current block + locals_of_current_block: BitSet, } 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> { // 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> { 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> { 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, - // 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, + // Cache of locals' information + local_kinds: IndexVec, } impl CanConstProp { - /// returns true if `local` can be propagated + /// Returns true if `local` can be propagated fn check(body: &Body<'_>) -> IndexVec { 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(); } } diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs new file mode 100644 index 00000000000..0cd1f37c9a7 --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs @@ -0,0 +1,6 @@ +// EMIT_MIR rustc.main.ConstProp.diff +#[allow(unconditional_panic)] +fn main() { + let y = 0; + let _z = 1 / y; +} diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff new file mode 100644 index 00000000000..333bf0e320b --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff @@ -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()) + // mir::Constant + // + span: $DIR/bad_op_div_by_zero.rs:3:11: 6:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs new file mode 100644 index 00000000000..26bccbb90ec --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs @@ -0,0 +1,6 @@ +// EMIT_MIR rustc.main.ConstProp.diff +#[allow(unconditional_panic)] +fn main() { + let y = 0; + let _z = 1 % y; +} diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff new file mode 100644 index 00000000000..c081b46366e --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff @@ -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()) + // mir::Constant + // + span: $DIR/bad_op_mod_by_zero.rs:3:11: 6:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs new file mode 100644 index 00000000000..e517e467c37 --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs @@ -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]; + } +} diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff new file mode 100644 index 00000000000..8ecb77752bb --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff @@ -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()) + // mir::Constant + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff new file mode 100644 index 00000000000..2778ec02724 --- /dev/null +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff @@ -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()) + // mir::Constant + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation.rs b/src/test/mir-opt/const_prop/scalar_literal_propagation.rs new file mode 100644 index 00000000000..a740e69dca2 --- /dev/null +++ b/src/test/mir-opt/const_prop/scalar_literal_propagation.rs @@ -0,0 +1,8 @@ +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let x = 1; + consume(x); +} + +#[inline(never)] +fn consume(_: u32) { } diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff new file mode 100644 index 00000000000..0183ff7716c --- /dev/null +++ b/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff @@ -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()) + // mir::Constant + // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12 + // + literal: Const { ty: fn(u32) {consume}, val: Value(Scalar()) } + } + + 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()) + // mir::Constant + // + span: $DIR/scalar_literal_propagation.rs:2:11: 5:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.rs b/src/test/mir-opt/const_prop/tuple_literal_propagation.rs new file mode 100644 index 00000000000..015607cbab1 --- /dev/null +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.rs @@ -0,0 +1,9 @@ +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let x = (1, 2); + + consume(x); +} + +#[inline(never)] +fn consume(_: (u32, u32)) { } diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation/rustc.main.ConstProp.diff new file mode 100644 index 00000000000..1511b361f58 --- /dev/null +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation/rustc.main.ConstProp.diff @@ -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()) + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 + // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(Scalar()) } + } + + 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()) + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:2:11: 6:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/simplify-arm-identity.rs b/src/test/mir-opt/simplify-arm-identity.rs index cc6aab7523f..24e91b3ff61 100644 --- a/src/test/mir-opt/simplify-arm-identity.rs +++ b/src/test/mir-opt/simplify-arm-identity.rs @@ -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), diff --git a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff new file mode 100644 index 00000000000..bf24bfb2c57 --- /dev/null +++ b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff @@ -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()) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:17:11: 23:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff new file mode 100644 index 00000000000..ff7183e57d2 --- /dev/null +++ b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff @@ -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()) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:17:11: 23:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + 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 + } + } + diff --git a/src/test/mir-opt/simplify_match.rs b/src/test/mir-opt/simplify_match.rs index 233f9ff4c40..b8e1ea6f981 100644 --- a/src/test/mir-opt/simplify_match.rs +++ b/src/test/mir-opt/simplify_match.rs @@ -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(), diff --git a/src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff b/src/test/mir-opt/simplify_match/rustc.main.ConstProp.diff similarity index 51% rename from src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff rename to src/test/mir-opt/simplify_match/rustc.main.ConstProp.diff index 68b1b70c52a..8003112c46c 100644 --- a/src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff +++ b/src/test/mir-opt/simplify_match/rustc.main.ConstProp.diff @@ -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 } } diff --git a/src/test/run-fail/divide-by-zero.rs b/src/test/run-fail/divide-by-zero.rs index fdb3f4842e5..ba93563154a 100644 --- a/src/test/run-fail/divide-by-zero.rs +++ b/src/test/run-fail/divide-by-zero.rs @@ -1,5 +1,5 @@ // error-pattern:attempt to divide by zero - +#[allow(unconditional_panic)] fn main() { let y = 0; let _z = 1 / y; diff --git a/src/test/run-fail/dst-raw-slice.rs b/src/test/run-fail/dst-raw-slice.rs index 561b1fb42ed..2575de7cc58 100644 --- a/src/test/run-fail/dst-raw-slice.rs +++ b/src/test/run-fail/dst-raw-slice.rs @@ -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 { diff --git a/src/test/run-fail/mod-zero.rs b/src/test/run-fail/mod-zero.rs index ac2959fcd38..f70b3ac920c 100644 --- a/src/test/run-fail/mod-zero.rs +++ b/src/test/run-fail/mod-zero.rs @@ -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; diff --git a/src/test/ui/mir/mir_detects_invalid_ops.rs b/src/test/ui/mir/mir_detects_invalid_ops.rs new file mode 100644 index 00000000000..0940dbe6a5e --- /dev/null +++ b/src/test/ui/mir/mir_detects_invalid_ops.rs @@ -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] + } +} diff --git a/src/test/ui/mir/mir_detects_invalid_ops.stderr b/src/test/ui/mir/mir_detects_invalid_ops.stderr new file mode 100644 index 00000000000..41f03789f23 --- /dev/null +++ b/src/test/ui/mir/mir_detects_invalid_ops.stderr @@ -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 +