11use either:: Either ;
2+ use rustc_data_structures:: graph:: dominators:: Dominators ;
23use rustc_index:: bit_set:: BitSet ;
34use rustc_index:: vec:: IndexVec ;
45use rustc_middle:: middle:: resolve_lifetime:: Set1 ;
@@ -65,6 +66,7 @@ enum LocationExtended {
6566
6667#[ derive( Debug ) ]
6768struct SsaLocals {
69+ dominators : Dominators < BasicBlock > ,
6870 /// Assignments to each local. This defines whether the local is SSA.
6971 assignments : IndexVec < Local , Set1 < LocationExtended > > ,
7072 /// We visit the body in reverse postorder, to ensure each local is assigned before it is used.
@@ -78,7 +80,8 @@ impl SsaLocals {
7880 let assignment_order = Vec :: new ( ) ;
7981
8082 let assignments = IndexVec :: from_elem ( Set1 :: Empty , & body. local_decls ) ;
81- let mut this = SsaLocals { assignments, assignment_order } ;
83+ let dominators = body. basic_blocks . dominators ( ) ;
84+ let mut this = SsaLocals { assignments, assignment_order, dominators } ;
8285
8386 let borrowed = borrowed_locals ( body) ;
8487 for ( local, decl) in body. local_decls . iter_enumerated ( ) {
@@ -117,7 +120,23 @@ impl<'tcx> Visitor<'tcx> for SsaLocals {
117120 PlaceContext :: MutatingUse ( _) => self . assignments [ local] = Set1 :: Many ,
118121 // Immutable borrows and AddressOf are taken into account in `SsaLocals::new` by
119122 // removing non-freeze locals.
120- PlaceContext :: NonMutatingUse ( _) | PlaceContext :: NonUse ( _) => { }
123+ PlaceContext :: NonMutatingUse ( _) => {
124+ let set = & mut self . assignments [ local] ;
125+ let assign_dominates = match * set {
126+ Set1 :: Empty | Set1 :: Many => false ,
127+ Set1 :: One ( LocationExtended :: Arg ) => true ,
128+ Set1 :: One ( LocationExtended :: Plain ( assign) ) => {
129+ assign. dominates ( loc, & self . dominators )
130+ }
131+ } ;
132+ // We are visiting a use that is not dominated by an assignment.
133+ // Either there is a cycle involved, or we are reading for uninitialized local.
134+ // Bail out.
135+ if !assign_dominates {
136+ * set = Set1 :: Many ;
137+ }
138+ }
139+ PlaceContext :: NonUse ( _) => { }
121140 }
122141 }
123142}
0 commit comments