From e2caebc4a61a39e6e618129f312bc4be174fb7be Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 28 Apr 2023 16:51:40 +0000 Subject: [PATCH 1/2] Add tests. --- .../address_of_pair.fn0.ConstProp.diff | 51 +++++++++++++++++++ tests/mir-opt/const_prop/address_of_pair.rs | 17 +++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff create mode 100644 tests/mir-opt/const_prop/address_of_pair.rs diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff new file mode 100644 index 0000000000000..8a8e869ba0316 --- /dev/null +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff @@ -0,0 +1,51 @@ +- // MIR for `fn0` before ConstProp ++ // MIR for `fn0` after ConstProp + + fn fn0() -> bool { + let mut _0: bool; // return place in scope 0 at $DIR/address_of_pair.rs:+0:17: +0:21 + let mut _1: !; // in scope 0 at $DIR/address_of_pair.rs:+0:22: +9:2 + let mut _2: (i32, bool); // in scope 0 at $DIR/address_of_pair.rs:+1:9: +1:17 + let _4: (); // in scope 0 at $DIR/address_of_pair.rs:+4:5: +6:6 + let mut _6: bool; // in scope 0 at $DIR/address_of_pair.rs:+7:16: +7:22 + scope 1 { + debug pair => _2; // in scope 1 at $DIR/address_of_pair.rs:+1:9: +1:17 + let _3: *mut bool; // in scope 1 at $DIR/address_of_pair.rs:+2:9: +2:12 + scope 2 { + debug ptr => _3; // in scope 2 at $DIR/address_of_pair.rs:+2:9: +2:12 + let _5: bool; // in scope 2 at $DIR/address_of_pair.rs:+7:9: +7:12 + scope 3 { + } + scope 4 { + debug ret => _5; // in scope 4 at $DIR/address_of_pair.rs:+7:9: +7:12 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/address_of_pair.rs:+1:9: +1:17 +- _2 = (const 1_i32, const false); // scope 0 at $DIR/address_of_pair.rs:+1:20: +1:30 ++ _2 = const (1_i32, false); // scope 0 at $DIR/address_of_pair.rs:+1:20: +1:30 + StorageLive(_3); // scope 1 at $DIR/address_of_pair.rs:+2:9: +2:12 + _3 = &raw mut (_2.1: bool); // scope 1 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL +- _2 = (const 1_i32, const false); // scope 2 at $DIR/address_of_pair.rs:+3:5: +3:22 ++ _2 = const (1_i32, false); // scope 2 at $DIR/address_of_pair.rs:+3:5: +3:22 + StorageLive(_4); // scope 2 at $DIR/address_of_pair.rs:+4:5: +6:6 + (*_3) = const true; // scope 3 at $DIR/address_of_pair.rs:+5:9: +5:20 + _4 = const (); // scope 3 at $DIR/address_of_pair.rs:+4:5: +6:6 + StorageDead(_4); // scope 2 at $DIR/address_of_pair.rs:+6:5: +6:6 + StorageLive(_5); // scope 2 at $DIR/address_of_pair.rs:+7:9: +7:12 + StorageLive(_6); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 +- _6 = (_2.1: bool); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 +- _5 = Not(move _6); // scope 2 at $DIR/address_of_pair.rs:+7:15: +7:22 ++ _6 = const false; // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 ++ _5 = const true; // scope 2 at $DIR/address_of_pair.rs:+7:15: +7:22 + StorageDead(_6); // scope 2 at $DIR/address_of_pair.rs:+7:21: +7:22 +- _0 = _5; // scope 4 at $DIR/address_of_pair.rs:+8:12: +8:15 ++ _0 = const true; // scope 4 at $DIR/address_of_pair.rs:+8:12: +8:15 + StorageDead(_5); // scope 2 at $DIR/address_of_pair.rs:+9:1: +9:2 + StorageDead(_3); // scope 1 at $DIR/address_of_pair.rs:+9:1: +9:2 + StorageDead(_2); // scope 0 at $DIR/address_of_pair.rs:+9:1: +9:2 + return; // scope 0 at $DIR/address_of_pair.rs:+9:2: +9:2 + } + } + diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs new file mode 100644 index 0000000000000..43dc9bae62534 --- /dev/null +++ b/tests/mir-opt/const_prop/address_of_pair.rs @@ -0,0 +1,17 @@ +// unit-test: ConstProp + +// EMIT_MIR address_of_pair.fn0.ConstProp.diff +pub fn fn0() -> bool { + let mut pair = (1, false); + let ptr = core::ptr::addr_of_mut!(pair.1); + pair = (1, false); + unsafe { + *ptr = true; + } + let ret = !pair.1; + return ret; +} + +pub fn main() { + println!("{}", fn0()); +} From 1ffe9059c31d17ea1b22099b0f64de0232ebadd5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 28 Apr 2023 16:57:40 +0000 Subject: [PATCH 2/2] Reject borrows of projections in ConstProp. --- .../rustc_mir_transform/src/const_prop.rs | 20 ++++++++++++++----- .../address_of_pair.fn0.ConstProp.diff | 15 +++++--------- .../const_prop_miscompile.bar.ConstProp.diff | 3 +-- .../const_prop_miscompile.foo.ConstProp.diff | 3 +-- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index b3a3a25ebe863..7f995c69a4879 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -714,13 +714,22 @@ impl CanConstProp { } } -impl Visitor<'_> for CanConstProp { +impl<'tcx> Visitor<'tcx> for CanConstProp { + fn visit_place(&mut self, place: &Place<'tcx>, mut context: PlaceContext, loc: Location) { + use rustc_middle::mir::visit::PlaceContext::*; + + // Dereferencing just read the addess of `place.local`. + if place.projection.first() == Some(&PlaceElem::Deref) { + context = NonMutatingUse(NonMutatingUseContext::Copy); + } + + self.visit_local(place.local, context, loc); + self.visit_projection(place.as_ref(), context, loc); + } + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { - // Projections are fine, because `&mut foo.x` will be caught by - // `MutatingUseContext::Borrow` elsewhere. - MutatingUse(MutatingUseContext::Projection) // These are just stores, where the storing is not propagatable, but there may be later // mutations of the same local via `Store` | MutatingUse(MutatingUseContext::Call) @@ -751,7 +760,6 @@ impl Visitor<'_> for CanConstProp { NonMutatingUse(NonMutatingUseContext::Copy) | NonMutatingUse(NonMutatingUseContext::Move) | NonMutatingUse(NonMutatingUseContext::Inspect) - | NonMutatingUse(NonMutatingUseContext::Projection) | NonMutatingUse(NonMutatingUseContext::PlaceMention) | NonUse(_) => {} @@ -771,6 +779,8 @@ impl Visitor<'_> for CanConstProp { trace!("local {:?} can't be propagated because it's used: {:?}", local, context); self.can_const_prop[local] = ConstPropMode::NoPropagation; } + MutatingUse(MutatingUseContext::Projection) + | NonMutatingUse(NonMutatingUseContext::Projection) => bug!("visit_place should not pass {context:?} for {local:?}"), } } } diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff index 8a8e869ba0316..d50b12044ceb2 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff @@ -23,25 +23,20 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/address_of_pair.rs:+1:9: +1:17 -- _2 = (const 1_i32, const false); // scope 0 at $DIR/address_of_pair.rs:+1:20: +1:30 -+ _2 = const (1_i32, false); // scope 0 at $DIR/address_of_pair.rs:+1:20: +1:30 + _2 = (const 1_i32, const false); // scope 0 at $DIR/address_of_pair.rs:+1:20: +1:30 StorageLive(_3); // scope 1 at $DIR/address_of_pair.rs:+2:9: +2:12 _3 = &raw mut (_2.1: bool); // scope 1 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL -- _2 = (const 1_i32, const false); // scope 2 at $DIR/address_of_pair.rs:+3:5: +3:22 -+ _2 = const (1_i32, false); // scope 2 at $DIR/address_of_pair.rs:+3:5: +3:22 + _2 = (const 1_i32, const false); // scope 2 at $DIR/address_of_pair.rs:+3:5: +3:22 StorageLive(_4); // scope 2 at $DIR/address_of_pair.rs:+4:5: +6:6 (*_3) = const true; // scope 3 at $DIR/address_of_pair.rs:+5:9: +5:20 _4 = const (); // scope 3 at $DIR/address_of_pair.rs:+4:5: +6:6 StorageDead(_4); // scope 2 at $DIR/address_of_pair.rs:+6:5: +6:6 StorageLive(_5); // scope 2 at $DIR/address_of_pair.rs:+7:9: +7:12 StorageLive(_6); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 -- _6 = (_2.1: bool); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 -- _5 = Not(move _6); // scope 2 at $DIR/address_of_pair.rs:+7:15: +7:22 -+ _6 = const false; // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 -+ _5 = const true; // scope 2 at $DIR/address_of_pair.rs:+7:15: +7:22 + _6 = (_2.1: bool); // scope 2 at $DIR/address_of_pair.rs:+7:16: +7:22 + _5 = Not(move _6); // scope 2 at $DIR/address_of_pair.rs:+7:15: +7:22 StorageDead(_6); // scope 2 at $DIR/address_of_pair.rs:+7:21: +7:22 -- _0 = _5; // scope 4 at $DIR/address_of_pair.rs:+8:12: +8:15 -+ _0 = const true; // scope 4 at $DIR/address_of_pair.rs:+8:12: +8:15 + _0 = _5; // scope 4 at $DIR/address_of_pair.rs:+8:12: +8:15 StorageDead(_5); // scope 2 at $DIR/address_of_pair.rs:+9:1: +9:2 StorageDead(_3); // scope 1 at $DIR/address_of_pair.rs:+9:1: +9:2 StorageDead(_2); // scope 0 at $DIR/address_of_pair.rs:+9:1: +9:2 diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff index def9fc6428fb6..a5f52d08957c8 100644 --- a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -19,8 +19,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 -- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 -+ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 + _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff index b54c10a140f2c..42ddc2a56208a 100644 --- a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff @@ -16,8 +16,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 -- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 -+ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 + _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14 _2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14 (*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +2:18