@@ -626,45 +626,36 @@ pub struct Map {
626
626
}
627
627
628
628
impl 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 {
631
636
locals : IndexVec :: new ( ) ,
632
637
projections : FxHashMap :: default ( ) ,
633
638
places : IndexVec :: new ( ) ,
634
639
value_count : 0 ,
635
640
inner_values : IndexVec :: new ( ) ,
636
641
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
+ } ;
652
643
let exclude = excluded_locals ( body) ;
653
- map. register_with_filter ( tcx, body, filter , exclude, value_limit) ;
644
+ map. register ( tcx, body, exclude, value_limit) ;
654
645
debug ! ( "registered {} places ({} nodes in total)" , map. value_count, map. places. len( ) ) ;
655
646
map
656
647
}
657
648
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 > (
660
651
& mut self ,
661
652
tcx : TyCtxt < ' tcx > ,
662
653
body : & Body < ' tcx > ,
663
- filter : impl Fn ( Ty < ' tcx > ) -> bool ,
664
654
exclude : BitSet < Local > ,
665
655
value_limit : Option < usize > ,
666
656
) {
667
657
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 ( ) ) ;
668
659
669
660
// Start by constructing the places for each bare local.
670
661
self . locals = IndexVec :: from_elem ( None , & body. local_decls ) ;
@@ -679,7 +670,7 @@ impl Map {
679
670
self . locals [ local] = Some ( place) ;
680
671
681
672
// 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) ;
683
674
}
684
675
685
676
// `place.elem1.elem2` with type `ty`.
@@ -702,7 +693,7 @@ impl Map {
702
693
}
703
694
704
695
// 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) ;
706
697
}
707
698
708
699
// Pre-compute the tree of ValueIndex nested in each PlaceIndex.
@@ -732,42 +723,35 @@ impl Map {
732
723
fn register_children < ' tcx > (
733
724
& mut self ,
734
725
tcx : TyCtxt < ' tcx > ,
726
+ param_env : ty:: ParamEnv < ' tcx > ,
735
727
place : PlaceIndex ,
736
728
ty : Ty < ' tcx > ,
737
- filter : & impl Fn ( Ty < ' tcx > ) -> bool ,
738
729
worklist : & mut VecDeque < ( PlaceIndex , Option < TrackElem > , TrackElem , Ty < ' tcx > ) > ,
739
730
) {
740
731
// 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 ( ) ) {
742
734
self . places [ place] . value_index = Some ( self . value_count . into ( ) ) ;
743
735
self . value_count += 1 ;
744
736
}
745
737
746
738
// For enums, directly create the `Discriminant`, as that's their main use.
747
739
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 ;
767
751
}
768
752
769
753
// 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| {
771
755
worklist. push_back ( (
772
756
place,
773
757
variant. map ( TrackElem :: Variant ) ,
0 commit comments