3434
3535use std:: fmt:: { Debug , Formatter } ;
3636
37- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
37+ use rustc_data_structures:: fx:: FxHashMap ;
3838use rustc_index:: vec:: IndexVec ;
3939use rustc_middle:: mir:: visit:: { MutatingUseContext , PlaceContext , Visitor } ;
4040use rustc_middle:: mir:: * ;
@@ -587,7 +587,8 @@ impl Map {
587587 filter : impl FnMut ( Ty < ' tcx > ) -> bool ,
588588 ) -> Self {
589589 let mut map = Self :: new ( ) ;
590- map. register_with_filter ( tcx, body, filter, & escaped_places ( body) ) ;
590+ let exclude = excluded_locals ( body) ;
591+ map. register_with_filter ( tcx, body, filter, & exclude) ;
591592 debug ! ( "registered {} places ({} nodes in total)" , map. value_count, map. places. len( ) ) ;
592593 map
593594 }
@@ -598,19 +599,14 @@ impl Map {
598599 tcx : TyCtxt < ' tcx > ,
599600 body : & Body < ' tcx > ,
600601 mut filter : impl FnMut ( Ty < ' tcx > ) -> bool ,
601- exclude : & FxHashSet < Place < ' tcx > > ,
602+ exclude : & IndexVec < Local , bool > ,
602603 ) {
603604 // We use this vector as stack, pushing and popping projections.
604605 let mut projection = Vec :: new ( ) ;
605606 for ( local, decl) in body. local_decls . iter_enumerated ( ) {
606- self . register_with_filter_rec (
607- tcx,
608- local,
609- & mut projection,
610- decl. ty ,
611- & mut filter,
612- exclude,
613- ) ;
607+ if !exclude[ local] {
608+ self . register_with_filter_rec ( tcx, local, & mut projection, decl. ty , & mut filter) ;
609+ }
614610 }
615611 }
616612
@@ -624,17 +620,10 @@ impl Map {
624620 projection : & mut Vec < PlaceElem < ' tcx > > ,
625621 ty : Ty < ' tcx > ,
626622 filter : & mut impl FnMut ( Ty < ' tcx > ) -> bool ,
627- exclude : & FxHashSet < Place < ' tcx > > ,
628623 ) {
629- let place = Place { local, projection : tcx. intern_place_elems ( projection) } ;
630- if exclude. contains ( & place) {
631- // This will also exclude all projections of the excluded place.
632- return ;
633- }
634-
635624 // Note: The framework supports only scalars for now.
636625 if filter ( ty) && ty. is_scalar ( ) {
637- trace ! ( "registering place: {:?}" , place ) ;
626+ // trace!("registering place {:?}", PlaceRef { local, projection: &*projection } );
638627
639628 // We know that the projection only contains trackable elements.
640629 let place = self . make_place ( local, projection) . unwrap ( ) ;
@@ -653,7 +642,7 @@ impl Map {
653642 return ;
654643 }
655644 projection. push ( PlaceElem :: Field ( field, ty) ) ;
656- self . register_with_filter_rec ( tcx, local, projection, ty, filter, exclude ) ;
645+ self . register_with_filter_rec ( tcx, local, projection, ty, filter) ;
657646 projection. pop ( ) ;
658647 } ) ;
659648 }
@@ -835,27 +824,27 @@ fn iter_fields<'tcx>(
835824 }
836825}
837826
838- /// Returns all places, that have their reference or address taken.
839- ///
840- /// This includes shared references, and also drops and `InlineAsm` out parameters.
841- fn escaped_places < ' tcx > ( body : & Body < ' tcx > ) -> FxHashSet < Place < ' tcx > > {
842- struct Collector < ' tcx > {
843- result : FxHashSet < Place < ' tcx > > ,
827+ /// Returns all locals with projections that have their reference or address taken.
828+ fn excluded_locals < ' tcx > ( body : & Body < ' tcx > ) -> IndexVec < Local , bool > {
829+ struct Collector {
830+ result : IndexVec < Local , bool > ,
844831 }
845832
846- impl < ' tcx > Visitor < ' tcx > for Collector < ' tcx > {
833+ impl < ' tcx > Visitor < ' tcx > for Collector {
847834 fn visit_place ( & mut self , place : & Place < ' tcx > , context : PlaceContext , _location : Location ) {
848835 if context. is_borrow ( )
849836 || context. is_address_of ( )
850837 || context. is_drop ( )
851838 || context == PlaceContext :: MutatingUse ( MutatingUseContext :: AsmOutput )
852839 {
853- self . result . insert ( * place) ;
840+ // A pointer to a place could be used to access other places with the same local,
841+ // hence we have to exclude the local completely.
842+ self . result [ place. local ] = true ;
854843 }
855844 }
856845 }
857846
858- let mut collector = Collector { result : FxHashSet :: default ( ) } ;
847+ let mut collector = Collector { result : IndexVec :: from_elem ( false , & body . local_decls ) } ;
859848 collector. visit_body ( body) ;
860849 collector. result
861850}
0 commit comments