diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 9654e189f2ed..29cf3977dc80 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1098,6 +1098,10 @@ macro_rules! super_body { } } + for var_debug_info in &$($mutability)? $body.var_debug_info { + $self.visit_var_debug_info(var_debug_info); + } + for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) { $self.visit_basic_block_data(bb, data); } @@ -1127,10 +1131,6 @@ macro_rules! super_body { ); } - for var_debug_info in &$($mutability)? $body.var_debug_info { - $self.visit_var_debug_info(var_debug_info); - } - $self.visit_span($(& $mutability)? $body.span); if let Some(required_consts) = &$($mutability)? $body.required_consts { diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index deb0a146476c..c5b53dbbd309 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -302,6 +302,7 @@ fn compute_replacement<'tcx>( return Replacer { tcx, targets: finder.targets, + remap_var_debug_infos: IndexVec::from_elem(None, body.local_decls()), storage_to_remove, allowed_replacements, any_replacement: false, @@ -381,6 +382,7 @@ fn fully_replaceable_locals(ssa: &SsaLocals) -> DenseBitSet { struct Replacer<'tcx> { tcx: TyCtxt<'tcx>, targets: IndexVec>, + remap_var_debug_infos: IndexVec>, storage_to_remove: DenseBitSet, allowed_replacements: FxHashSet<(Local, Location)>, any_replacement: bool, @@ -392,21 +394,45 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { } fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) { - // If the debuginfo is a pointer to another place - // and it's a reborrow: see through it - while let VarDebugInfoContents::Place(ref mut place) = debuginfo.value + if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value && place.projection.is_empty() - && let Value::Pointer(target, _) = self.targets[place.local] - && let &[PlaceElem::Deref] = &target.projection[..] { - *place = Place::from(target.local); - self.any_replacement = true; + let mut new_local = place.local; + + // If the debuginfo is a pointer to another place + // and it's a reborrow: see through it + while let Value::Pointer(target, _) = self.targets[new_local] + && let &[PlaceElem::Deref] = &target.projection[..] + { + new_local = target.local; + } + if place.local != new_local { + self.remap_var_debug_infos[place.local] = Some(new_local); + place.local = new_local; + + self.any_replacement = true; + } } // Simplify eventual projections left inside `debuginfo`. self.super_var_debug_info(debuginfo); } + fn visit_statement_debuginfo( + &mut self, + stmt_debuginfo: &mut StmtDebugInfo<'tcx>, + location: Location, + ) { + let local = match stmt_debuginfo { + StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => local, + }; + if let Some(target) = self.remap_var_debug_infos[*local] { + *local = target; + self.any_replacement = true; + } + self.super_statement_debuginfo(stmt_debuginfo, location); + } + fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) { loop { let Some((&PlaceElem::Deref, rest)) = place.projection.split_first() else { return }; @@ -437,8 +463,9 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { { stmt.make_nop(true); } - // Do not remove assignments as they may still be useful for debuginfo. - _ => self.super_statement(stmt, loc), + _ => {} } + // Do not remove assignments as they may still be useful for debuginfo. + self.super_statement(stmt, loc); } } diff --git a/tests/mir-opt/debuginfo/ref_prop.remap_debuginfo_locals.ReferencePropagation.diff b/tests/mir-opt/debuginfo/ref_prop.remap_debuginfo_locals.ReferencePropagation.diff index 87941aadab4d..2d93b1d842fa 100644 --- a/tests/mir-opt/debuginfo/ref_prop.remap_debuginfo_locals.ReferencePropagation.diff +++ b/tests/mir-opt/debuginfo/ref_prop.remap_debuginfo_locals.ReferencePropagation.diff @@ -25,7 +25,7 @@ - StorageDead(_2); - StorageDead(_3); - StorageDead(_1); -+ // DBG: _1 = &(*_5); ++ // DBG: _5 = &(*_5); _0 = const (); return; } diff --git a/tests/mir-opt/debuginfo/ref_prop.rs b/tests/mir-opt/debuginfo/ref_prop.rs index 5f2f1ce09c70..60d68ba178a7 100644 --- a/tests/mir-opt/debuginfo/ref_prop.rs +++ b/tests/mir-opt/debuginfo/ref_prop.rs @@ -1,4 +1,3 @@ -// skip-filecheck //@ test-mir-pass: ReferencePropagation //@ compile-flags: -g -Zub_checks=false -Zinline-mir -Zmir-enable-passes=+DeadStoreElimination-initial @@ -9,6 +8,11 @@ use std::intrinsics::mir::*; // EMIT_MIR ref_prop.remap_debuginfo_locals.ReferencePropagation.diff pub fn remap_debuginfo_locals() { + // CHECK-LABEL: fn remap_debuginfo_locals() + // CHECK: debug a => [[a:_.*]]; + // CHECK: bb0: + // CHECK-NEXT: [[a]] = const + // CHECK-NEXT: DBG: [[a]] = &(*[[a]]); foo(&0); } diff --git a/tests/crashes/147485.rs b/tests/ui/debuginfo/ref_prop_debuginfo-147485.rs similarity index 79% rename from tests/crashes/147485.rs rename to tests/ui/debuginfo/ref_prop_debuginfo-147485.rs index 86f3705e636b..15899626aff7 100644 --- a/tests/crashes/147485.rs +++ b/tests/ui/debuginfo/ref_prop_debuginfo-147485.rs @@ -1,6 +1,8 @@ -//@ known-bug: #147485 +//@ build-pass //@ compile-flags: -g -O +// Regression test for #147485. + #![crate_type = "lib"] pub fn f(x: *const usize) -> &'static usize {