diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 731060bd2c2b8..4bc47bc8890eb 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -335,7 +335,7 @@ fn compute_replacement<'tcx>( // // This also allows to detect cases where `target.local` is not replaceable, // and mark it as such. - if let &[PlaceElem::Deref] = &target.projection[..] { + if target.is_indirect_first_projection() { assert!(perform_opt); self.allowed_replacements.insert((target.local, loc)); place.local = target.local; diff --git a/tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff new file mode 100644 index 0000000000000..6b3928451a2ed --- /dev/null +++ b/tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff @@ -0,0 +1,30 @@ +- // MIR for `maybe_dead_field_reborrow` before ReferencePropagation ++ // MIR for `maybe_dead_field_reborrow` after ReferencePropagation + + fn maybe_dead_field_reborrow(_1: bool) -> i32 { + let mut _0: i32; + let mut _2: (i32, i32); + let mut _3: &mut (i32, i32); + let mut _4: &mut i32; + + bb0: { + StorageLive(_2); + _2 = (const 0_i32, const 0_i32); + _3 = &mut _2; + ((*_3).0: i32) = const 1_i32; +- _4 = &mut ((*_3).0: i32); + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; + } + + bb1: { + StorageDead(_2); + goto -> bb2; + } + + bb2: { +- _0 = copy (*_4); ++ _0 = copy ((*_3).0: i32); + return; + } + } + diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index c4b63b6313c23..8220689baf1a4 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -776,6 +776,36 @@ fn maybe_dead(m: bool) { } } +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +fn maybe_dead_field_reborrow(m: bool) -> i32 { + // CHECK-LABEL: fn maybe_dead_field_reborrow( + // CHECK: [[r:_.*]] = &mut {{_.*}}; + // CHECK: ((*[[r]]).0: i32) = const 1_i32; + + use std::intrinsics::mir::*; + mir! { + let x: (i32, i32); + let r: &mut (i32, i32); + let r2: &mut i32; + { + StorageLive(x); + x = (0, 0); + r = &mut x; + (*r).0 = 1; + r2 = &mut (*r).0; + match m { true => bb1, _ => bb2 } + } + bb1 = { + StorageDead(x); + Goto(bb2) + } + bb2 = { + RET = *r2; + Return() + } + } +} + fn mut_raw_then_mut_shr() -> (i32, i32) { // CHECK-LABEL: fn mut_raw_then_mut_shr( // CHECK-NOT: (*{{_.*}}) @@ -875,6 +905,7 @@ fn main() { multiple_storage(); dominate_storage(); maybe_dead(true); + maybe_dead_field_reborrow(true); mut_raw_then_mut_shr(); unique_with_copies(); debuginfo(); @@ -889,6 +920,7 @@ fn main() { // EMIT_MIR reference_prop.multiple_storage.ReferencePropagation.diff // EMIT_MIR reference_prop.dominate_storage.ReferencePropagation.diff // EMIT_MIR reference_prop.maybe_dead.ReferencePropagation.diff +// EMIT_MIR reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff // EMIT_MIR reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff // EMIT_MIR reference_prop.unique_with_copies.ReferencePropagation.diff // EMIT_MIR reference_prop.debuginfo.ReferencePropagation.diff