@@ -581,6 +581,14 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
581581        } 
582582    } 
583583
584+     /// Retrieve the value stored for a place, or ⊤ if it is not tracked. 
585+ pub  fn  get_len ( & self ,  place :  PlaceRef < ' _ > ,  map :  & Map )  -> V  { 
586+         match  map. find_len ( place)  { 
587+             Some ( place)  => self . get_idx ( place,  map) , 
588+             None  => V :: TOP , 
589+         } 
590+     } 
591+ 
584592    /// Retrieve the value stored for a place index, or ⊤ if it is not tracked. 
585593pub  fn  get_idx ( & self ,  place :  PlaceIndex ,  map :  & Map )  -> V  { 
586594        match  & self . 0  { 
@@ -626,45 +634,36 @@ pub struct Map {
626634} 
627635
628636impl  Map  { 
629-     fn  new ( )  -> Self  { 
630-         Self  { 
637+     /// Returns a map that only tracks places whose type has scalar layout. 
638+ /// 
639+ /// This is currently the only way to create a [`Map`]. The way in which the tracked places are 
640+ /// chosen is an implementation detail and may not be relied upon (other than that their type 
641+ /// are scalars). 
642+ pub  fn  new < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  body :  & Body < ' tcx > ,  value_limit :  Option < usize > )  -> Self  { 
643+         let  mut  map = Self  { 
631644            locals :  IndexVec :: new ( ) , 
632645            projections :  FxHashMap :: default ( ) , 
633646            places :  IndexVec :: new ( ) , 
634647            value_count :  0 , 
635648            inner_values :  IndexVec :: new ( ) , 
636649            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 ( ) ; 
650+         } ; 
652651        let  exclude = excluded_locals ( body) ; 
653-         map. register_with_filter ( tcx,  body,  filter ,  exclude,  value_limit) ; 
652+         map. register ( tcx,  body,  exclude,  value_limit) ; 
654653        debug ! ( "registered {} places ({} nodes in total)" ,  map. value_count,  map. places. len( ) ) ; 
655654        map
656655    } 
657656
658-     /// Register all non-excluded places that pass the filter . 
659- fn  register_with_filter < ' tcx > ( 
657+     /// Register all non-excluded places that have scalar layout . 
658+ fn  register < ' tcx > ( 
660659        & mut  self , 
661660        tcx :  TyCtxt < ' tcx > , 
662661        body :  & Body < ' tcx > , 
663-         filter :  impl  Fn ( Ty < ' tcx > )  -> bool , 
664662        exclude :  BitSet < Local > , 
665663        value_limit :  Option < usize > , 
666664    )  { 
667665        let  mut  worklist = VecDeque :: with_capacity ( value_limit. unwrap_or ( body. local_decls . len ( ) ) ) ; 
666+         let  param_env = tcx. param_env_reveal_all_normalized ( body. source . def_id ( ) ) ; 
668667
669668        // Start by constructing the places for each bare local. 
670669        self . locals  = IndexVec :: from_elem ( None ,  & body. local_decls ) ; 
@@ -679,7 +678,7 @@ impl Map {
679678            self . locals [ local]  = Some ( place) ; 
680679
681680            // And push the eventual children places to the worklist. 
682-             self . register_children ( tcx,  place,  decl. ty ,   & filter ,  & mut  worklist) ; 
681+             self . register_children ( tcx,  param_env ,   place,  decl. ty ,  & mut  worklist) ; 
683682        } 
684683
685684        // `place.elem1.elem2` with type `ty`. 
@@ -702,7 +701,7 @@ impl Map {
702701            } 
703702
704703            // And push the eventual children places to the worklist. 
705-             self . register_children ( tcx,  place ,  ty ,   & filter ,  & mut  worklist) ; 
704+             self . register_children ( tcx,  param_env ,  place ,  ty ,  & mut  worklist) ; 
706705        } 
707706
708707        // Pre-compute the tree of ValueIndex nested in each PlaceIndex. 
@@ -732,42 +731,52 @@ impl Map {
732731fn  register_children < ' tcx > ( 
733732        & mut  self , 
734733        tcx :  TyCtxt < ' tcx > , 
734+         param_env :  ty:: ParamEnv < ' tcx > , 
735735        place :  PlaceIndex , 
736736        ty :  Ty < ' tcx > , 
737-         filter :  & impl  Fn ( Ty < ' tcx > )  -> bool , 
738737        worklist :  & mut  VecDeque < ( PlaceIndex ,  Option < TrackElem > ,  TrackElem ,  Ty < ' tcx > ) > , 
739738    )  { 
740739        // 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)  { 
740+         assert ! ( self . places[ place] . value_index. is_none( ) ) ; 
741+         if  tcx. layout_of ( param_env. and ( ty) ) . map_or ( false ,  |layout| layout. abi . is_scalar ( ) )  { 
742742            self . places [ place] . value_index  = Some ( self . value_count . into ( ) ) ; 
743743            self . value_count  += 1 ; 
744744        } 
745745
746746        // For enums, directly create the `Discriminant`, as that's their main use. 
747747        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-             } 
748+             // Prepend new child to the linked list. 
749+             let  discr = self . places . push ( PlaceInfo :: new ( Some ( TrackElem :: Discriminant ) ) ) ; 
750+             self . places [ discr] . next_sibling  = self . places [ place] . first_child ; 
751+             self . places [ place] . first_child  = Some ( discr) ; 
752+             let  old = self . projections . insert ( ( place,  TrackElem :: Discriminant ) ,  discr) ; 
753+             assert ! ( old. is_none( ) ) ; 
754+ 
755+             // Allocate a value slot since it doesn't have one. 
756+             assert ! ( self . places[ discr] . value_index. is_none( ) ) ; 
757+             self . places [ discr] . value_index  = Some ( self . value_count . into ( ) ) ; 
758+             self . value_count  += 1 ; 
759+         } 
760+ 
761+         if  let  Some ( ref_ty)  = ty. builtin_deref ( true )  && let  ty:: Slice ( ..)  = ref_ty. ty . kind ( )  { 
762+             assert ! ( self . places[ place] . value_index. is_none( ) ,  "slices are not scalars" ) ; 
763+ 
764+             // Prepend new child to the linked list. 
765+             let  len = self . places . push ( PlaceInfo :: new ( Some ( TrackElem :: DerefLen ) ) ) ; 
766+             self . places [ len] . next_sibling  = self . places [ place] . first_child ; 
767+             self . places [ place] . first_child  = Some ( len) ; 
768+ 
769+             let  old = self . projections . insert ( ( place,  TrackElem :: DerefLen ) ,  len) ; 
770+             assert ! ( old. is_none( ) ) ; 
771+ 
772+             // Allocate a value slot since it doesn't have one. 
773+             assert ! (  self . places[ len] . value_index. is_none( )  ) ; 
774+             self . places [ len] . value_index  = Some ( self . value_count . into ( ) ) ; 
775+             self . value_count  += 1 ; 
767776        } 
768777
769778        // Recurse with all fields of this place. 
770-         iter_fields ( ty,  tcx,  ty :: ParamEnv :: reveal_all ( ) ,  |variant,  field,  ty| { 
779+         iter_fields ( ty,  tcx,  param_env ,  |variant,  field,  ty| { 
771780            worklist. push_back ( ( 
772781                place, 
773782                variant. map ( TrackElem :: Variant ) , 
@@ -834,6 +843,11 @@ impl Map {
834843        self . find_extra ( place,  [ TrackElem :: Discriminant ] ) 
835844    } 
836845
846+     /// Locates the given place and applies `DerefLen`, if it exists in the tree. 
847+ pub  fn  find_len ( & self ,  place :  PlaceRef < ' _ > )  -> Option < PlaceIndex >  { 
848+         self . find_extra ( place,  [ TrackElem :: DerefLen ] ) 
849+     } 
850+ 
837851    /// Iterate over all direct children. 
838852pub  fn  children ( & self ,  parent :  PlaceIndex )  -> impl  Iterator < Item  = PlaceIndex >  + ' _  { 
839853        Children :: new ( self ,  parent) 
@@ -985,6 +999,8 @@ pub enum TrackElem {
985999    Field ( FieldIdx ) , 
9861000    Variant ( VariantIdx ) , 
9871001    Discriminant , 
1002+     // Length of a slice. 
1003+     DerefLen , 
9881004} 
9891005
9901006impl < V ,  T >  TryFrom < ProjectionElem < V ,  T > >  for  TrackElem  { 
@@ -1124,6 +1140,9 @@ fn debug_with_context_rec<V: Debug + Eq>(
11241140                    format ! ( "{}.{}" ,  place_str,  field. index( ) ) 
11251141                } 
11261142            } 
1143+             TrackElem :: DerefLen  => { 
1144+                 format ! ( "Len(*{})" ,  place_str) 
1145+             } 
11271146        } ; 
11281147        debug_with_context_rec ( child,  & child_place_str,  new,  old,  map,  f) ?; 
11291148    } 
0 commit comments