@@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
154
154
context : PlaceContext ,
155
155
location : Location ) {
156
156
debug ! ( "visit_place(place={:?}, context={:?})" , place, context) ;
157
+ let mut context = context;
157
158
let cx = self . fx . cx ;
158
159
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 ( ) {
186
178
return ;
187
179
}
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
+ }
188
190
}
189
- }
190
191
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
+ } ;
198
206
}
199
- }
200
207
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
+ } ) ;
202
213
}
203
214
204
215
fn visit_local ( & mut self ,
0 commit comments