From 0589cd0f0a9536d028c2118c5b08ee5872d9e9d7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 9 Jun 2023 13:13:42 +0200 Subject: [PATCH] mir opt: fix subtype handling --- compiler/rustc_mir_transform/src/dest_prop.rs | 13 +++++++++++++ compiler/rustc_mir_transform/src/ssa.rs | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 78758e2db28ab..9faf2b03f62ba 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 7a0d3a025f365..5495e3532f76a 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; }