3838//! It must also not contain any indexing projections, since those take an arbitrary `Local` as
3939//! the index, and that local might only be initialized shortly before `dest` is used.
4040//!
41- //! Subtle case: If `dest` is a, or projects through a union, then we have to make sure that there
42- //! remains an assignment to it, since that sets the "active field" of the union. But if `src` is
43- //! a ZST, it might not be initialized, so there might not be any use of it before the assignment,
44- //! and performing the optimization would simply delete the assignment, leaving `dest`
45- //! uninitialized.
46- //!
4741//! * `src` must be a bare `Local` without any indirections or field projections (FIXME: Is this a
4842//! fundamental restriction or just current impl state?). It can be copied or moved by the
4943//! assignment.
@@ -103,7 +97,6 @@ use rustc_index::{
10397 bit_set:: { BitMatrix , BitSet } ,
10498 vec:: IndexVec ,
10599} ;
106- use rustc_middle:: mir:: tcx:: PlaceTy ;
107100use rustc_middle:: mir:: visit:: { MutVisitor , PlaceContext , Visitor } ;
108101use rustc_middle:: mir:: { dump_mir, PassWhere } ;
109102use rustc_middle:: mir:: {
@@ -135,7 +128,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
135128 fn run_pass ( & self , tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
136129 let def_id = body. source . def_id ( ) ;
137130
138- let candidates = find_candidates ( tcx , body) ;
131+ let candidates = find_candidates ( body) ;
139132 if candidates. is_empty ( ) {
140133 debug ! ( "{:?}: no dest prop candidates, done" , def_id) ;
141134 return ;
@@ -803,9 +796,8 @@ struct CandidateAssignment<'tcx> {
803796/// comment) and also throw out assignments that involve a local that has its address taken or is
804797/// otherwise ineligible (eg. locals used as array indices are ignored because we cannot propagate
805798/// arbitrary places into array indices).
806- fn find_candidates < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & Body < ' tcx > ) -> Vec < CandidateAssignment < ' tcx > > {
799+ fn find_candidates < ' tcx > ( body : & Body < ' tcx > ) -> Vec < CandidateAssignment < ' tcx > > {
807800 let mut visitor = FindAssignments {
808- tcx,
809801 body,
810802 candidates : Vec :: new ( ) ,
811803 ever_borrowed_locals : ever_borrowed_locals ( body) ,
@@ -816,7 +808,6 @@ fn find_candidates<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> Vec<CandidateA
816808}
817809
818810struct FindAssignments < ' a , ' tcx > {
819- tcx : TyCtxt < ' tcx > ,
820811 body : & ' a Body < ' tcx > ,
821812 candidates : Vec < CandidateAssignment < ' tcx > > ,
822813 ever_borrowed_locals : BitSet < Local > ,
@@ -845,10 +836,11 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
845836 return ;
846837 }
847838
848- // Can't optimize if both locals ever have their address taken (can introduce
849- // aliasing).
850- // FIXME: This can be smarter and take `StorageDead` into account (which
851- // invalidates borrows).
839+ // Can't optimize if either local ever has their address taken. This optimization does
840+ // liveness analysis only based on assignments, and a local can be live even if its
841+ // never assigned to again, because a reference to it might be live.
842+ // FIXME: This can be smarter and take `StorageDead` into account (which invalidates
843+ // borrows).
852844 if self . ever_borrowed_locals . contains ( dest. local )
853845 || self . ever_borrowed_locals . contains ( src. local )
854846 {
@@ -862,22 +854,11 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
862854 return ;
863855 }
864856
865- // Handle the "subtle case" described above by rejecting any `dest` that is or
866- // projects through a union.
867- let mut place_ty = PlaceTy :: from_ty ( self . body . local_decls [ dest. local ] . ty ) ;
868- if place_ty. ty . is_union ( ) {
869- return ;
870- }
871857 for elem in dest. projection {
872858 if let PlaceElem :: Index ( _) = elem {
873859 // `dest` contains an indexing projection.
874860 return ;
875861 }
876-
877- place_ty = place_ty. projection_ty ( self . tcx , elem) ;
878- if place_ty. ty . is_union ( ) {
879- return ;
880- }
881862 }
882863
883864 self . candidates . push ( CandidateAssignment {
0 commit comments