@@ -180,6 +180,15 @@ macro_rules! make_mir_visitor {
180180 self . super_place( place, context, location) ;
181181 }
182182
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+
183192 visit_place_fns!( $( $mutability) ?) ;
184193
185194 /// This is called for every constant in the MIR body and every `required_consts`
@@ -1182,6 +1191,45 @@ macro_rules! visit_place_fns {
11821191 | PlaceElem :: Downcast ( ..) => None ,
11831192 }
11841193 }
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+ }
11851233 } ;
11861234
11871235 ( ) => {
@@ -1194,13 +1242,15 @@ macro_rules! visit_place_fns {
11941242 self . super_projection( place_ref, context, location) ;
11951243 }
11961244
1197- fn visit_projection_elem(
1245+ fn visit_projection_elem< P > (
11981246 & mut self ,
1199- place_ref: PlaceRef < ' tcx> ,
1247+ place_ref: P ,
12001248 elem: PlaceElem <' tcx>,
12011249 context: PlaceContext ,
12021250 location: Location ,
1203- ) {
1251+ ) where
1252+ P : ProjectionBase <' tcx>,
1253+ {
12041254 self . super_projection_elem( place_ref, elem, context, location) ;
12051255 }
12061256
@@ -1235,13 +1285,15 @@ macro_rules! visit_place_fns {
12351285 }
12361286 }
12371287
1238- fn super_projection_elem(
1288+ fn super_projection_elem< P > (
12391289 & mut self ,
1240- _place_ref: PlaceRef < ' tcx> ,
1290+ _place_ref: P ,
12411291 elem: PlaceElem <' tcx>,
12421292 context: PlaceContext ,
12431293 location: Location ,
1244- ) {
1294+ ) where
1295+ P : ProjectionBase <' tcx>,
1296+ {
12451297 match elem {
12461298 ProjectionElem :: OpaqueCast ( ty)
12471299 | ProjectionElem :: Subtype ( ty)
@@ -1267,6 +1319,28 @@ macro_rules! visit_place_fns {
12671319 | ProjectionElem :: Downcast ( _, _) => { }
12681320 }
12691321 }
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+ }
12701344 } ;
12711345}
12721346
@@ -1492,3 +1566,28 @@ where
14921566 self . visit_projection ( place. as_ref ( ) , ctxt, location) ;
14931567 }
14941568}
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