about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan MacKenzie <ecstaticmorse@gmail.com>2020-01-24 15:32:22 -0800
committerDylan MacKenzie <ecstaticmorse@gmail.com>2020-02-13 18:42:12 -0800
commite2c80477532b54271cbb7249d0bb36d7b257fca2 (patch)
tree6276d4cc6e47e19b711d62f938856656df2756d0
parent99b96199a6f47a8ff97c0df8dda849b5f6f58abf (diff)
downloadrust-e2c80477532b54271cbb7249d0bb36d7b257fca2.tar.gz
rust-e2c80477532b54271cbb7249d0bb36d7b257fca2.zip
Kill move paths of dead variants
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 5b2264c2a65..bd710bc429a 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -3,7 +3,8 @@
 //! zero-sized structure.
 
 use rustc::mir::{self, Body, Location};
-use rustc::ty::TyCtxt;
+use rustc::ty::layout::VariantIdx;
+use rustc::ty::{self, TyCtxt};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
 
@@ -12,12 +13,13 @@ use super::MoveDataParamEnv;
 use crate::util::elaborate_drops::DropFlagState;
 
 use super::generic::{AnalysisDomain, GenKill, GenKillAnalysis};
-use super::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex};
+use super::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
 use super::{BottomValue, GenKillSet};
 
 use super::drop_flag_effects_for_function_entry;
 use super::drop_flag_effects_for_location;
 use super::on_lookup_result_bits;
+use crate::dataflow::drop_flag_effects;
 
 mod borrowed_locals;
 mod indirect_mutation;
@@ -338,6 +340,37 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
             },
         );
     }
+
+    fn discriminant_switch_effect(
+        &self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _block: mir::BasicBlock,
+        enum_place: &mir::Place<'tcx>,
+        _adt: &ty::AdtDef,
+        variant: VariantIdx,
+    ) {
+        let enum_mpi = match self.move_data().rev_lookup.find(enum_place.as_ref()) {
+            LookupResult::Exact(mpi) => mpi,
+            LookupResult::Parent(_) => return,
+        };
+
+        // Kill all move paths that correspond to variants other than this one
+        let move_paths = &self.move_data().move_paths;
+        let enum_path = &move_paths[enum_mpi];
+        for (mpi, variant_path) in enum_path.children(move_paths) {
+            trans.kill(mpi);
+            match variant_path.place.projection.last().unwrap() {
+                mir::ProjectionElem::Downcast(_, idx) if *idx == variant => continue,
+                _ => drop_flag_effects::on_all_children_bits(
+                    self.tcx,
+                    self.body,
+                    self.move_data(),
+                    mpi,
+                    |mpi| trans.kill(mpi),
+                ),
+            }
+        }
+    }
 }
 
 impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {