about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
authorKyle Huey <khuey@kylehuey.com>2024-08-03 21:23:35 -0700
committerKyle Huey <khuey@kylehuey.com>2024-08-03 21:23:35 -0700
commit709406fc6c792bd5dd0d07fbc59c4437b3d47f95 (patch)
treed3fb71f143025348749b9eef0c62c4baf05e8951 /compiler/rustc_mir_transform/src
parenta6043039ad3aef48e08d72a3e32545accdee427a (diff)
downloadrust-709406fc6c792bd5dd0d07fbc59c4437b3d47f95.tar.gz
rust-709406fc6c792bd5dd0d07fbc59c4437b3d47f95.zip
When deduplicating unreachable blocks, erase the source information.
After deduplication the block conceptually belongs to multiple locations
in the source. Although these blocks are unreachable, in #123341 we did
come across a real side effect, an unreachable block that survives into
the compiled code can cause a debugger to set a breakpoint on the wrong
instruction. Erasing the source information ensures that a debugger will
never be misled into thinking that the unreachable block is worth setting
a breakpoint on, especially after #128627.

Technically we don't need to erase the source information if all the
deduplicated blocks have identical source information, but tracking
that seems like more effort than it's worth.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs11
1 files changed, 11 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 5bbe3bb747f..4fe8cf6213f 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -31,6 +31,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
+use rustc_span::DUMMY_SP;
 use smallvec::SmallVec;
 
 pub enum SimplifyCfg {
@@ -318,6 +319,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
     let mut orig_index = 0;
     let mut used_index = 0;
     let mut kept_unreachable = None;
+    let mut deduplicated_unreachable = false;
     basic_blocks.raw.retain(|bbdata| {
         let orig_bb = BasicBlock::new(orig_index);
         if !reachable.contains(orig_bb) {
@@ -330,6 +332,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
             let kept_unreachable = *kept_unreachable.get_or_insert(used_bb);
             if kept_unreachable != used_bb {
                 replacements[orig_index] = kept_unreachable;
+                deduplicated_unreachable = true;
                 orig_index += 1;
                 return false;
             }
@@ -341,6 +344,14 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
         true
     });
 
+    // If we deduplicated unreachable blocks we erase their source_info as we
+    // can no longer attribute their code to a particular location in the
+    // source.
+    if deduplicated_unreachable {
+        basic_blocks[kept_unreachable.unwrap()].terminator_mut().source_info =
+            SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE };
+    }
+
     for block in basic_blocks {
         for target in block.terminator_mut().successors_mut() {
             *target = replacements[target.index()];