@@ -626,45 +626,36 @@ pub struct Map {
626626}
627627
628628impl Map {
629- fn new ( ) -> Self {
630- Self {
629+ /// Returns a map that only tracks places whose type has scalar layout.
630+ ///
631+ /// This is currently the only way to create a [`Map`]. The way in which the tracked places are
632+ /// chosen is an implementation detail and may not be relied upon (other than that their type
633+ /// are scalars).
634+ pub fn new < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & Body < ' tcx > , value_limit : Option < usize > ) -> Self {
635+ let mut map = Self {
631636 locals : IndexVec :: new ( ) ,
632637 projections : FxHashMap :: default ( ) ,
633638 places : IndexVec :: new ( ) ,
634639 value_count : 0 ,
635640 inner_values : IndexVec :: new ( ) ,
636641 inner_values_buffer : Vec :: new ( ) ,
637- }
638- }
639-
640- /// Returns a map that only tracks places whose type passes the filter.
641- ///
642- /// This is currently the only way to create a [`Map`]. The way in which the tracked places are
643- /// chosen is an implementation detail and may not be relied upon (other than that their type
644- /// passes the filter).
645- pub fn from_filter < ' tcx > (
646- tcx : TyCtxt < ' tcx > ,
647- body : & Body < ' tcx > ,
648- filter : impl Fn ( Ty < ' tcx > ) -> bool ,
649- value_limit : Option < usize > ,
650- ) -> Self {
651- let mut map = Self :: new ( ) ;
642+ } ;
652643 let exclude = excluded_locals ( body) ;
653- map. register_with_filter ( tcx, body, filter , exclude, value_limit) ;
644+ map. register ( tcx, body, exclude, value_limit) ;
654645 debug ! ( "registered {} places ({} nodes in total)" , map. value_count, map. places. len( ) ) ;
655646 map
656647 }
657648
658- /// Register all non-excluded places that pass the filter .
659- fn register_with_filter < ' tcx > (
649+ /// Register all non-excluded places that have scalar layout .
650+ fn register < ' tcx > (
660651 & mut self ,
661652 tcx : TyCtxt < ' tcx > ,
662653 body : & Body < ' tcx > ,
663- filter : impl Fn ( Ty < ' tcx > ) -> bool ,
664654 exclude : BitSet < Local > ,
665655 value_limit : Option < usize > ,
666656 ) {
667657 let mut worklist = VecDeque :: with_capacity ( value_limit. unwrap_or ( body. local_decls . len ( ) ) ) ;
658+ let param_env = tcx. param_env_reveal_all_normalized ( body. source . def_id ( ) ) ;
668659
669660 // Start by constructing the places for each bare local.
670661 self . locals = IndexVec :: from_elem ( None , & body. local_decls ) ;
@@ -679,7 +670,7 @@ impl Map {
679670 self . locals [ local] = Some ( place) ;
680671
681672 // And push the eventual children places to the worklist.
682- self . register_children ( tcx, place, decl. ty , & filter , & mut worklist) ;
673+ self . register_children ( tcx, param_env , place, decl. ty , & mut worklist) ;
683674 }
684675
685676 // `place.elem1.elem2` with type `ty`.
@@ -702,7 +693,7 @@ impl Map {
702693 }
703694
704695 // And push the eventual children places to the worklist.
705- self . register_children ( tcx, place , ty , & filter , & mut worklist) ;
696+ self . register_children ( tcx, param_env , place , ty , & mut worklist) ;
706697 }
707698
708699 // Pre-compute the tree of ValueIndex nested in each PlaceIndex.
@@ -732,42 +723,35 @@ impl Map {
732723 fn register_children < ' tcx > (
733724 & mut self ,
734725 tcx : TyCtxt < ' tcx > ,
726+ param_env : ty:: ParamEnv < ' tcx > ,
735727 place : PlaceIndex ,
736728 ty : Ty < ' tcx > ,
737- filter : & impl Fn ( Ty < ' tcx > ) -> bool ,
738729 worklist : & mut VecDeque < ( PlaceIndex , Option < TrackElem > , TrackElem , Ty < ' tcx > ) > ,
739730 ) {
740731 // Allocate a value slot if it doesn't have one, and the user requested one.
741- if self . places [ place] . value_index . is_none ( ) && filter ( ty) {
732+ assert ! ( self . places[ place] . value_index. is_none( ) ) ;
733+ if tcx. layout_of ( param_env. and ( ty) ) . map_or ( false , |layout| layout. abi . is_scalar ( ) ) {
742734 self . places [ place] . value_index = Some ( self . value_count . into ( ) ) ;
743735 self . value_count += 1 ;
744736 }
745737
746738 // For enums, directly create the `Discriminant`, as that's their main use.
747739 if ty. is_enum ( ) {
748- let discr_ty = ty. discriminant_ty ( tcx) ;
749- if filter ( discr_ty) {
750- let discr = * self
751- . projections
752- . entry ( ( place, TrackElem :: Discriminant ) )
753- . or_insert_with ( || {
754- // Prepend new child to the linked list.
755- let next = self . places . push ( PlaceInfo :: new ( Some ( TrackElem :: Discriminant ) ) ) ;
756- self . places [ next] . next_sibling = self . places [ place] . first_child ;
757- self . places [ place] . first_child = Some ( next) ;
758- next
759- } ) ;
760-
761- // Allocate a value slot if it doesn't have one.
762- if self . places [ discr] . value_index . is_none ( ) {
763- self . places [ discr] . value_index = Some ( self . value_count . into ( ) ) ;
764- self . value_count += 1 ;
765- }
766- }
740+ // Prepend new child to the linked list.
741+ let discr = self . places . push ( PlaceInfo :: new ( Some ( TrackElem :: Discriminant ) ) ) ;
742+ self . places [ discr] . next_sibling = self . places [ place] . first_child ;
743+ self . places [ place] . first_child = Some ( discr) ;
744+ let old = self . projections . insert ( ( place, TrackElem :: Discriminant ) , discr) ;
745+ assert ! ( old. is_none( ) ) ;
746+
747+ // Allocate a value slot if it doesn't have one.
748+ assert ! ( self . places[ discr] . value_index. is_none( ) ) ;
749+ self . places [ discr] . value_index = Some ( self . value_count . into ( ) ) ;
750+ self . value_count += 1 ;
767751 }
768752
769753 // Recurse with all fields of this place.
770- iter_fields ( ty, tcx, ty :: ParamEnv :: reveal_all ( ) , |variant, field, ty| {
754+ iter_fields ( ty, tcx, param_env , |variant, field, ty| {
771755 worklist. push_back ( (
772756 place,
773757 variant. map ( TrackElem :: Variant ) ,
0 commit comments