@@ -92,6 +92,86 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
92
92
self . first_assignment [ local] = location;
93
93
}
94
94
}
95
+
96
+ fn process_place ( & mut self ,
97
+ place_ref : & mir:: PlaceRef < ' _ , ' tcx > ,
98
+ context : PlaceContext ,
99
+ location : Location ) {
100
+ let cx = self . fx . cx ;
101
+
102
+ if let Some ( proj) = place_ref. projection {
103
+ // Allow uses of projections that are ZSTs or from scalar fields.
104
+ let is_consume = match context {
105
+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) |
106
+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move ) => true ,
107
+ _ => false
108
+ } ;
109
+ if is_consume {
110
+ let base_ty =
111
+ mir:: Place :: ty_from ( place_ref. base , & proj. base , self . fx . mir , cx. tcx ( ) ) ;
112
+ let base_ty = self . fx . monomorphize ( & base_ty) ;
113
+
114
+ // ZSTs don't require any actual memory access.
115
+ let elem_ty = base_ty
116
+ . projection_ty ( cx. tcx ( ) , & proj. elem )
117
+ . ty ;
118
+ let elem_ty = self . fx . monomorphize ( & elem_ty) ;
119
+ if cx. layout_of ( elem_ty) . is_zst ( ) {
120
+ return ;
121
+ }
122
+
123
+ if let mir:: ProjectionElem :: Field ( ..) = proj. elem {
124
+ let layout = cx. layout_of ( base_ty. ty ) ;
125
+ if cx. is_backend_immediate ( layout) || cx. is_backend_scalar_pair ( layout) {
126
+ // Recurse with the same context, instead of `Projection`,
127
+ // potentially stopping at non-operand projections,
128
+ // which would trigger `not_ssa` on locals.
129
+ self . process_place (
130
+ & mir:: PlaceRef {
131
+ base : place_ref. base ,
132
+ projection : & proj. base ,
133
+ } ,
134
+ context,
135
+ location,
136
+ ) ;
137
+ return ;
138
+ }
139
+ }
140
+ }
141
+
142
+ // A deref projection only reads the pointer, never needs the place.
143
+ if let mir:: ProjectionElem :: Deref = proj. elem {
144
+ self . process_place (
145
+ & mir:: PlaceRef {
146
+ base : place_ref. base ,
147
+ projection : & proj. base ,
148
+ } ,
149
+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) ,
150
+ location
151
+ ) ;
152
+ return ;
153
+ }
154
+ }
155
+
156
+ // FIXME this is super_place code, is repeated here to avoid cloning place or changing
157
+ // visit_place API
158
+ let mut context = context;
159
+
160
+ if place_ref. projection . is_some ( ) {
161
+ context = if context. is_mutating_use ( ) {
162
+ PlaceContext :: MutatingUse ( MutatingUseContext :: Projection )
163
+ } else {
164
+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Projection )
165
+ } ;
166
+ }
167
+
168
+ self . visit_place_base ( place_ref. base , context, location) ;
169
+
170
+ if let Some ( box proj) = place_ref. projection {
171
+ self . visit_projection ( place_ref. base , proj, context, location) ;
172
+ }
173
+ }
174
+
95
175
}
96
176
97
177
impl < ' mir , ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > Visitor < ' tcx >
@@ -158,63 +238,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
158
238
context : PlaceContext ,
159
239
location : Location ) {
160
240
debug ! ( "visit_place(place={:?}, context={:?})" , place, context) ;
161
- let cx = self . fx . cx ;
162
-
163
- if let Some ( proj) = & place. projection {
164
- // Allow uses of projections that are ZSTs or from scalar fields.
165
- let is_consume = match context {
166
- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) |
167
- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move ) => true ,
168
- _ => false
169
- } ;
170
- if is_consume {
171
- let base_ty = mir:: Place :: ty_from ( & place. base , & proj. base , self . fx . mir , cx. tcx ( ) ) ;
172
- let base_ty = self . fx . monomorphize ( & base_ty) ;
173
-
174
- // ZSTs don't require any actual memory access.
175
- let elem_ty = base_ty
176
- . projection_ty ( cx. tcx ( ) , & proj. elem )
177
- . ty ;
178
- let elem_ty = self . fx . monomorphize ( & elem_ty) ;
179
- if cx. layout_of ( elem_ty) . is_zst ( ) {
180
- return ;
181
- }
182
-
183
- if let mir:: ProjectionElem :: Field ( ..) = proj. elem {
184
- let layout = cx. layout_of ( base_ty. ty ) ;
185
- if cx. is_backend_immediate ( layout) || cx. is_backend_scalar_pair ( layout) {
186
- // Recurse with the same context, instead of `Projection`,
187
- // potentially stopping at non-operand projections,
188
- // which would trigger `not_ssa` on locals.
189
- self . visit_place (
190
- // FIXME do not clone
191
- & mir:: Place {
192
- base : place. base . clone ( ) ,
193
- projection : proj. base . clone ( ) ,
194
- } ,
195
- context,
196
- location,
197
- ) ;
198
- return ;
199
- }
200
- }
201
- }
202
-
203
- // A deref projection only reads the pointer, never needs the place.
204
- if let mir:: ProjectionElem :: Deref = proj. elem {
205
- return self . visit_place (
206
- // FIXME do not clone
207
- & mir:: Place {
208
- base : place. base . clone ( ) ,
209
- projection : proj. base . clone ( ) ,
210
- } ,
211
- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) ,
212
- location
213
- ) ;
214
- }
215
- }
216
241
217
- self . super_place ( place, context, location) ;
242
+ let place_ref = mir:: PlaceRef {
243
+ base : & place. base ,
244
+ projection : & place. projection ,
245
+ } ;
246
+ self . process_place ( & place_ref, context, location) ;
218
247
}
219
248
220
249
fn visit_local ( & mut self ,
0 commit comments