@@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
154154 context : PlaceContext ,
155155 location : Location ) {
156156 debug ! ( "visit_place(place={:?}, context={:?})" , place, context) ;
157+ let mut context = context;
157158 let cx = self . fx . cx ;
158159
159- if let mir:: Place :: Projection ( ref proj) = * place {
160- // Allow uses of projections that are ZSTs or from scalar fields.
161- let is_consume = match context {
162- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) |
163- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move ) => true ,
164- _ => false
165- } ;
166- if is_consume {
167- let base_ty = proj. base . ty ( self . fx . mir , cx. tcx ( ) ) ;
168- let base_ty = self . fx . monomorphize ( & base_ty) ;
169-
170- // ZSTs don't require any actual memory access.
171- let elem_ty = base_ty
172- . projection_ty ( cx. tcx ( ) , & proj. elem )
173- . ty ;
174- let elem_ty = self . fx . monomorphize ( & elem_ty) ;
175- if cx. layout_of ( elem_ty) . is_zst ( ) {
176- return ;
177- }
178-
179- if let mir:: ProjectionElem :: Field ( ..) = proj. elem {
180- let layout = cx. layout_of ( base_ty. ty ) ;
181- if cx. is_backend_immediate ( layout) || cx. is_backend_scalar_pair ( layout) {
182- // Recurse with the same context, instead of `Projection`,
183- // potentially stopping at non-operand projections,
184- // which would trigger `not_ssa` on locals.
185- self . visit_place ( & proj. base , context, location) ;
160+ place. iterate ( |place_base, place_projections| {
161+ for proj in place_projections {
162+ // Allow uses of projections that are ZSTs or from scalar fields.
163+ let is_consume = match context {
164+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) |
165+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move ) => true ,
166+ _ => false
167+ } ;
168+ if is_consume {
169+ let base_ty = proj. base . ty ( self . fx . mir , cx. tcx ( ) ) ;
170+ let base_ty = self . fx . monomorphize ( & base_ty) ;
171+
172+ // ZSTs don't require any actual memory access.
173+ let elem_ty = base_ty
174+ . projection_ty ( cx. tcx ( ) , & proj. elem )
175+ . ty ;
176+ let elem_ty = self . fx . monomorphize ( & elem_ty) ;
177+ if cx. layout_of ( elem_ty) . is_zst ( ) {
186178 return ;
187179 }
180+
181+ if let mir:: ProjectionElem :: Field ( ..) = proj. elem {
182+ let layout = cx. layout_of ( base_ty. ty ) ;
183+ if cx. is_backend_immediate ( layout) || cx. is_backend_scalar_pair ( layout) {
184+ // Recurse with the same context, instead of `Projection`,
185+ // potentially stopping at non-operand projections,
186+ // which would trigger `not_ssa` on locals.
187+ continue ;
188+ }
189+ }
188190 }
189- }
190191
191- // A deref projection only reads the pointer, never needs the place.
192- if let mir:: ProjectionElem :: Deref = proj. elem {
193- return self . visit_place (
194- & proj. base ,
195- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) ,
196- location
197- ) ;
192+ // A deref projection only reads the pointer, never needs the place.
193+ if let mir:: ProjectionElem :: Deref = proj. elem {
194+ return self . visit_place (
195+ & proj. base ,
196+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) ,
197+ location
198+ ) ;
199+ }
200+
201+ context = if context. is_mutating_use ( ) {
202+ PlaceContext :: MutatingUse ( MutatingUseContext :: Projection )
203+ } else {
204+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Projection )
205+ } ;
198206 }
199- }
200207
201- self . super_place ( place, context, location) ;
208+ // Default base visit behavior
209+ if let mir:: PlaceBase :: Local ( local) = place_base {
210+ self . visit_local ( local, context, location) ;
211+ }
212+ } ) ;
202213 }
203214
204215 fn visit_local ( & mut self ,
0 commit comments