@@ -179,6 +179,25 @@ struct SsaVisitor {
179179 assignment_order : Vec < Local > ,
180180}
181181
182+ impl SsaVisitor {
183+ fn check_assignment_dominates ( & mut self , local : Local , loc : Location ) {
184+ let set = & mut self . assignments [ local] ;
185+ let assign_dominates = match * set {
186+ Set1 :: Empty | Set1 :: Many => false ,
187+ Set1 :: One ( LocationExtended :: Arg ) => true ,
188+ Set1 :: One ( LocationExtended :: Plain ( assign) ) => {
189+ assign. successor_within_block ( ) . dominates ( loc, & self . dominators )
190+ }
191+ } ;
192+ // We are visiting a use that is not dominated by an assignment.
193+ // Either there is a cycle involved, or we are reading for uninitialized local.
194+ // Bail out.
195+ if !assign_dominates {
196+ * set = Set1 :: Many ;
197+ }
198+ }
199+ }
200+
182201impl < ' tcx > Visitor < ' tcx > for SsaVisitor {
183202 fn visit_local ( & mut self , local : Local , ctxt : PlaceContext , loc : Location ) {
184203 match ctxt {
@@ -192,24 +211,26 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
192211 // Immutable borrows are taken into account in `SsaLocals::new` by
193212 // removing non-freeze locals.
194213 PlaceContext :: NonMutatingUse ( _) => {
195- let set = & mut self . assignments [ local] ;
196- let assign_dominates = match * set {
197- Set1 :: Empty | Set1 :: Many => false ,
198- Set1 :: One ( LocationExtended :: Arg ) => true ,
199- Set1 :: One ( LocationExtended :: Plain ( assign) ) => {
200- assign. successor_within_block ( ) . dominates ( loc, & self . dominators )
201- }
202- } ;
203- // We are visiting a use that is not dominated by an assignment.
204- // Either there is a cycle involved, or we are reading for uninitialized local.
205- // Bail out.
206- if !assign_dominates {
207- * set = Set1 :: Many ;
208- }
214+ self . check_assignment_dominates ( local, loc) ;
209215 }
210216 PlaceContext :: NonUse ( _) => { }
211217 }
212218 }
219+
220+ fn visit_place ( & mut self , place : & Place < ' tcx > , ctxt : PlaceContext , loc : Location ) {
221+ if place. projection . first ( ) == Some ( & PlaceElem :: Deref ) {
222+ // Do not do anything for storage statements and debuginfo.
223+ if ctxt. is_use ( ) {
224+ // A use through a `deref` only reads from the local, and cannot write to it.
225+ let new_ctxt = PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Projection ) ;
226+
227+ self . visit_projection ( place. as_ref ( ) , new_ctxt, loc) ;
228+ self . check_assignment_dominates ( place. local , loc) ;
229+ }
230+ return ;
231+ }
232+ self . super_place ( place, ctxt, loc) ;
233+ }
213234}
214235
215236#[ instrument( level = "trace" , skip( ssa, body) ) ]
0 commit comments