about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-06-09 13:13:42 +0200
committerlcnr <rust@lcnr.de>2023-06-19 09:06:42 +0200
commit0589cd0f0a9536d028c2118c5b08ee5872d9e9d7 (patch)
treeb585dd8e3e28ddbf1fed0ca85e8fdceb25b71029
parent46af169ec599be332d52a4093e3207202130b7d6 (diff)
downloadrust-0589cd0f0a9536d028c2118c5b08ee5872d9e9d7.tar.gz
rust-0589cd0f0a9536d028c2118c5b08ee5872d9e9d7.zip
mir opt: fix subtype handling
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs13
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs7
2 files changed, 20 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 78758e2db28..9faf2b03f62 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -37,6 +37,10 @@
 //!   if they do not consistently refer to the same place in memory. This is satisfied if they do
 //!   not contain any indirection through a pointer or any indexing projections.
 //!
+//! * `p` and `q` must have the **same type**. If we replace a local with a subtype or supertype,
+//!   we may end up with a differnet vtable for that local. See the `subtyping-impacts-selection`
+//!   tests for an example where that causes issues.
+//!
 //! * We need to make sure that the goal of "merging the memory" is actually structurally possible
 //!   in MIR. For example, even if all the other conditions are satisfied, there is no way to
 //!   "merge" `_5.foo` and `_6.bar`. For now, we ensure this by requiring that both `p` and `q` are
@@ -134,6 +138,7 @@ use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::HasLocalDecls;
 use rustc_middle::mir::{dump_mir, PassWhere};
 use rustc_middle::mir::{
     traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue,
@@ -769,6 +774,14 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {
                 return;
             }
 
+            // As described at the top of this file, we do not touch locals which have different types.
+            let src_ty = self.body.local_decls()[src].ty;
+            let dest_ty = self.body.local_decls()[dest].ty;
+            if src_ty != dest_ty {
+                trace!("skipped `{src:?} = {dest:?}` due to subtyping: {src_ty} != {dest_ty}");
+                return;
+            }
+
             // Also, we need to make sure that MIR actually allows the `src` to be removed
             if is_local_required(src, self.body) {
                 return;
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 7a0d3a025f3..5495e3532f7 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -271,6 +271,13 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
         else { continue };
 
         let Some(rhs) = place.as_local() else { continue };
+        let local_ty = body.local_decls()[local].ty;
+        let rhs_ty = body.local_decls()[rhs].ty;
+        if local_ty != rhs_ty {
+            trace!("skipped `{local:?} = {rhs:?}` due to subtyping: {local_ty} != {rhs_ty}");
+            continue;
+        }
+
         if !ssa.is_ssa(rhs) {
             continue;
         }