@@ -180,6 +180,15 @@ macro_rules! make_mir_visitor {
180
180
self . super_place( place, context, location) ;
181
181
}
182
182
183
+ fn visit_compound_place(
184
+ & mut self ,
185
+ place: & $( $mutability) ? CompoundPlace <' tcx>,
186
+ context: PlaceContext ,
187
+ location: Location ,
188
+ ) {
189
+ self . super_compound_place( place, context, location) ;
190
+ }
191
+
183
192
visit_place_fns!( $( $mutability) ?) ;
184
193
185
194
/// This is called for every constant in the MIR body and every `required_consts`
@@ -1182,6 +1191,45 @@ macro_rules! visit_place_fns {
1182
1191
| PlaceElem :: Downcast ( ..) => None ,
1183
1192
}
1184
1193
}
1194
+
1195
+ fn super_compound_place(
1196
+ & mut self ,
1197
+ place: & mut CompoundPlace <' tcx>,
1198
+ context: PlaceContext ,
1199
+ location: Location ,
1200
+ ) {
1201
+ self . visit_local( & mut place. local, context, location) ;
1202
+
1203
+ if let Some ( new_projection_chain) =
1204
+ self . process_projection_chain( & place. projection_chain, location)
1205
+ {
1206
+ place. projection_chain = self . tcx( ) . mk_place_elem_chain( & new_projection_chain) ;
1207
+ }
1208
+ }
1209
+
1210
+ fn process_projection_chain<' a>(
1211
+ & mut self ,
1212
+ projection_chain: & ' a [ & ' tcx List <PlaceElem <' tcx>>] ,
1213
+ location: Location ,
1214
+ ) -> Option <Vec <& ' tcx List <PlaceElem <' tcx>>>> {
1215
+ let mut projection_chain = Cow :: Borrowed ( projection_chain) ;
1216
+
1217
+ for i in 0 ..projection_chain. len( ) {
1218
+ if let Some ( segment) = projection_chain. get( i) {
1219
+ if let Some ( segment) = self . process_projection( segment, location) {
1220
+ // This converts the borrowed projection chain into `Cow::Owned(_)` and returns a
1221
+ // clone of the projection chain so we can mutate and reintern later.
1222
+ let vec = projection_chain. to_mut( ) ;
1223
+ vec[ i] = self . tcx( ) . mk_place_elems( & segment) ;
1224
+ }
1225
+ }
1226
+ }
1227
+
1228
+ match projection_chain {
1229
+ Cow :: Borrowed ( _) => None ,
1230
+ Cow :: Owned ( vec) => Some ( vec) ,
1231
+ }
1232
+ }
1185
1233
} ;
1186
1234
1187
1235
( ) => {
@@ -1194,13 +1242,15 @@ macro_rules! visit_place_fns {
1194
1242
self . super_projection( place_ref, context, location) ;
1195
1243
}
1196
1244
1197
- fn visit_projection_elem(
1245
+ fn visit_projection_elem< P > (
1198
1246
& mut self ,
1199
- place_ref: PlaceRef < ' tcx> ,
1247
+ place_ref: P ,
1200
1248
elem: PlaceElem <' tcx>,
1201
1249
context: PlaceContext ,
1202
1250
location: Location ,
1203
- ) {
1251
+ ) where
1252
+ P : ProjectionBase <' tcx>,
1253
+ {
1204
1254
self . super_projection_elem( place_ref, elem, context, location) ;
1205
1255
}
1206
1256
@@ -1235,13 +1285,15 @@ macro_rules! visit_place_fns {
1235
1285
}
1236
1286
}
1237
1287
1238
- fn super_projection_elem(
1288
+ fn super_projection_elem< P > (
1239
1289
& mut self ,
1240
- _place_ref: PlaceRef < ' tcx> ,
1290
+ _place_ref: P ,
1241
1291
elem: PlaceElem <' tcx>,
1242
1292
context: PlaceContext ,
1243
1293
location: Location ,
1244
- ) {
1294
+ ) where
1295
+ P : ProjectionBase <' tcx>,
1296
+ {
1245
1297
match elem {
1246
1298
ProjectionElem :: OpaqueCast ( ty)
1247
1299
| ProjectionElem :: Subtype ( ty)
@@ -1267,6 +1319,28 @@ macro_rules! visit_place_fns {
1267
1319
| ProjectionElem :: Downcast ( _, _) => { }
1268
1320
}
1269
1321
}
1322
+
1323
+ fn super_compound_place(
1324
+ & mut self ,
1325
+ place: & CompoundPlace <' tcx>,
1326
+ mut context: PlaceContext ,
1327
+ location: Location ,
1328
+ ) {
1329
+ if !place. projection_chain. is_empty( ) && context. is_use( ) {
1330
+ // ^ Only change the context if it is a real use, not a "use" in debuginfo.
1331
+ context = if context. is_mutating_use( ) {
1332
+ PlaceContext :: MutatingUse ( MutatingUseContext :: Projection )
1333
+ } else {
1334
+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Projection )
1335
+ } ;
1336
+ }
1337
+
1338
+ self . visit_local( place. local, context, location) ;
1339
+
1340
+ for ( base, elem) in place. iter_projections( ) . rev( ) {
1341
+ self . visit_projection_elem( base, elem, context, location) ;
1342
+ }
1343
+ }
1270
1344
} ;
1271
1345
}
1272
1346
@@ -1492,3 +1566,28 @@ where
1492
1566
self . visit_projection ( place. as_ref ( ) , ctxt, location) ;
1493
1567
}
1494
1568
}
1569
+
1570
+ /// Base of a projection in [`Visitor::visit_projection_elem`].
1571
+ pub trait ProjectionBase < ' tcx > : Debug + Copy {
1572
+ fn ty < D : ?Sized > ( & self , local_decls : & D , tcx : TyCtxt < ' tcx > ) -> PlaceTy < ' tcx >
1573
+ where
1574
+ D : HasLocalDecls < ' tcx > ;
1575
+ }
1576
+
1577
+ impl < ' tcx > ProjectionBase < ' tcx > for PlaceRef < ' tcx > {
1578
+ fn ty < D : ?Sized > ( & self , local_decls : & D , tcx : TyCtxt < ' tcx > ) -> PlaceTy < ' tcx >
1579
+ where
1580
+ D : HasLocalDecls < ' tcx > ,
1581
+ {
1582
+ self . ty ( local_decls, tcx)
1583
+ }
1584
+ }
1585
+
1586
+ impl < ' tcx > ProjectionBase < ' tcx > for CompoundPlaceRef < ' tcx > {
1587
+ fn ty < D : ?Sized > ( & self , local_decls : & D , tcx : TyCtxt < ' tcx > ) -> PlaceTy < ' tcx >
1588
+ where
1589
+ D : HasLocalDecls < ' tcx > ,
1590
+ {
1591
+ self . ty ( local_decls, tcx)
1592
+ }
1593
+ }
0 commit comments