@@ -11,6 +11,7 @@ use crate::middle::cstore::CrateStoreDyn;
1111
1212use rustc_target:: spec:: abi:: Abi ;
1313use rustc_data_structures:: svh:: Svh ;
14+ use rustc_data_structures:: indexed_vec:: IndexVec ;
1415use syntax:: ast:: { self , Name , NodeId } ;
1516use syntax:: source_map:: Spanned ;
1617use syntax:: ext:: base:: MacroKind ;
@@ -161,6 +162,13 @@ impl Forest {
161162 }
162163}
163164
165+ /// This type is effectively a `HashMap<HirId, Entry<'hir>>`,
166+ /// but is implemented by 3 layers of arrays.
167+ /// - the outer layer is `[A; 2]` and correspond to the 2 address spaces `DefIndex`es can be in
168+ /// - then we have `A = Vec<Option<B>>` mapping a `DefIndex`'s index to a inner value
169+ /// - which is `B = IndexVec<ItemLocalId, Option<Entry<'hir>>` which finally gives you the `Entry`.
170+ pub ( super ) type HirEntryMap < ' hir > = [ Vec < Option < IndexVec < ItemLocalId , Option < Entry < ' hir > > > > > ; 2 ] ;
171+
164172/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
165173#[ derive( Clone ) ]
166174pub struct Map < ' hir > {
@@ -174,7 +182,7 @@ pub struct Map<'hir> {
174182 /// The SVH of the local crate.
175183 pub crate_hash : Svh ,
176184
177- map : FxHashMap < HirId , Entry < ' hir > > ,
185+ map : HirEntryMap < ' hir > ,
178186
179187 definitions : & ' hir Definitions ,
180188
@@ -183,6 +191,12 @@ pub struct Map<'hir> {
183191}
184192
185193impl < ' hir > Map < ' hir > {
194+ #[ inline]
195+ fn lookup ( & self , id : HirId ) -> Option < & Entry < ' hir > > {
196+ let local_map = self . map [ id. owner . address_space ( ) . index ( ) ] . get ( id. owner . as_array_index ( ) ) ?;
197+ local_map. as_ref ( ) ?. get ( id. local_id ) ?. as_ref ( )
198+ }
199+
186200 /// Registers a read in the dependency graph of the AST node with
187201 /// the given `id`. This needs to be called each time a public
188202 /// function returns the HIR for a node -- in other words, when it
@@ -191,7 +205,7 @@ impl<'hir> Map<'hir> {
191205 /// read recorded). If the function just returns a DefId or
192206 /// NodeId, no actual content was returned, so no read is needed.
193207 pub fn read ( & self , hir_id : HirId ) {
194- if let Some ( entry) = self . map . get ( & hir_id) {
208+ if let Some ( entry) = self . lookup ( hir_id) {
195209 self . dep_graph . read_index ( entry. dep_node ) ;
196210 } else {
197211 bug ! ( "called `HirMap::read()` with invalid `HirId`: {:?}" , hir_id)
@@ -378,12 +392,8 @@ impl<'hir> Map<'hir> {
378392 } )
379393 }
380394
381- fn entry_count ( & self ) -> usize {
382- self . map . len ( )
383- }
384-
385395 fn find_entry ( & self , id : HirId ) -> Option < Entry < ' hir > > {
386- self . map . get ( & id) . cloned ( )
396+ self . lookup ( id) . cloned ( )
387397 }
388398
389399 pub fn krate ( & self ) -> & ' hir Crate {
@@ -433,7 +443,7 @@ impl<'hir> Map<'hir> {
433443 /// item (possibly associated), a closure, or a `hir::AnonConst`.
434444 pub fn body_owner ( & self , BodyId { hir_id } : BodyId ) -> NodeId {
435445 let parent = self . get_parent_node_by_hir_id ( hir_id) ;
436- assert ! ( self . map . get ( & parent) . map_or( false , |e| e. is_body_owner( hir_id) ) ) ;
446+ assert ! ( self . lookup ( parent) . map_or( false , |e| e. is_body_owner( hir_id) ) ) ;
437447 self . hir_to_node_id ( parent)
438448 }
439449
@@ -1004,6 +1014,34 @@ impl<'hir> Map<'hir> {
10041014 attrs. unwrap_or ( & [ ] )
10051015 }
10061016
1017+ /// Returns an iterator that yields all the hir ids in the map.
1018+ fn all_ids < ' a > ( & ' a self ) -> impl Iterator < Item = HirId > + ' a {
1019+ // This code is a bit awkward because the map is implemented as 3 levels of arrays,
1020+ // see the comment on `HirEntryMap`.
1021+ let map = & self . map ;
1022+
1023+ // Look at both the def index address spaces
1024+ let spaces = [ DefIndexAddressSpace :: Low , DefIndexAddressSpace :: High ] . iter ( ) . cloned ( ) ;
1025+ spaces. flat_map ( move |space| {
1026+ // Iterate over all the indices in the address space and return a reference to
1027+ // local maps and their index given that they exist.
1028+ let local_maps = map[ space. index ( ) ] . iter ( ) . enumerate ( ) . filter_map ( |( i, local_map) | {
1029+ local_map. as_ref ( ) . map ( |m| ( i, m) )
1030+ } ) ;
1031+
1032+ local_maps. flat_map ( move |( array_index, local_map) | {
1033+ // Iterate over each valid entry in the local map
1034+ local_map. iter_enumerated ( ) . filter_map ( move |( i, entry) | entry. map ( move |_| {
1035+ // Reconstruct the HirId based on the 3 indices we used to find it
1036+ HirId {
1037+ owner : DefIndex :: from_array_index ( array_index, space) ,
1038+ local_id : i,
1039+ }
1040+ } ) )
1041+ } )
1042+ } )
1043+ }
1044+
10071045 /// Returns an iterator that yields the node id's with paths that
10081046 /// match `parts`. (Requires `parts` is non-empty.)
10091047 ///
@@ -1012,13 +1050,16 @@ impl<'hir> Map<'hir> {
10121050 /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
10131051 /// any other such items it can find in the map.
10141052 pub fn nodes_matching_suffix < ' a > ( & ' a self , parts : & ' a [ String ] )
1015- -> NodesMatchingSuffix < ' a , ' hir > {
1016- NodesMatchingSuffix {
1053+ -> impl Iterator < Item = NodeId > + ' a {
1054+ let nodes = NodesMatchingSuffix {
10171055 map : self ,
10181056 item_name : parts. last ( ) . unwrap ( ) ,
10191057 in_which : & parts[ ..parts. len ( ) - 1 ] ,
1020- idx : ast:: CRATE_NODE_ID ,
1021- }
1058+ } ;
1059+
1060+ self . all_ids ( ) . filter ( move |hir| nodes. matces_suffix ( * hir) ) . map ( move |hir| {
1061+ self . hir_to_node_id ( hir)
1062+ } )
10221063 }
10231064
10241065 pub fn span ( & self , id : NodeId ) -> Span {
@@ -1097,21 +1138,20 @@ impl<'hir> Map<'hir> {
10971138 }
10981139}
10991140
1100- pub struct NodesMatchingSuffix < ' a , ' hir : ' a > {
1101- map : & ' a Map < ' hir > ,
1141+ pub struct NodesMatchingSuffix < ' a > {
1142+ map : & ' a Map < ' a > ,
11021143 item_name : & ' a String ,
11031144 in_which : & ' a [ String ] ,
1104- idx : NodeId ,
11051145}
11061146
1107- impl < ' a , ' hir > NodesMatchingSuffix < ' a , ' hir > {
1147+ impl < ' a > NodesMatchingSuffix < ' a > {
11081148 /// Returns `true` only if some suffix of the module path for parent
11091149 /// matches `self.in_which`.
11101150 ///
11111151 /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
11121152 /// returns true if parent's path ends with the suffix
11131153 /// `x_0::x_1::...::x_k`.
1114- fn suffix_matches ( & self , parent : NodeId ) -> bool {
1154+ fn suffix_matches ( & self , parent : HirId ) -> bool {
11151155 let mut cursor = parent;
11161156 for part in self . in_which . iter ( ) . rev ( ) {
11171157 let ( mod_id, mod_name) = match find_first_mod_parent ( self . map , cursor) {
@@ -1121,7 +1161,7 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> {
11211161 if mod_name != & * * part {
11221162 return false ;
11231163 }
1124- cursor = self . map . get_parent ( mod_id) ;
1164+ cursor = self . map . get_parent_item ( mod_id) ;
11251165 }
11261166 return true ;
11271167
@@ -1131,14 +1171,14 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> {
11311171 // If `id` itself is a mod named `m` with parent `p`, then
11321172 // returns `Some(id, m, p)`. If `id` has no mod in its parent
11331173 // chain, then returns `None`.
1134- fn find_first_mod_parent < ' a > ( map : & ' a Map < ' _ > , mut id : NodeId ) -> Option < ( NodeId , Name ) > {
1174+ fn find_first_mod_parent < ' a > ( map : & ' a Map < ' _ > , mut id : HirId ) -> Option < ( HirId , Name ) > {
11351175 loop {
1136- if let Node :: Item ( item) = map. find ( id) ? {
1176+ if let Node :: Item ( item) = map. find_by_hir_id ( id) ? {
11371177 if item_is_mod ( & item) {
11381178 return Some ( ( id, item. ident . name ) )
11391179 }
11401180 }
1141- let parent = map. get_parent ( id) ;
1181+ let parent = map. get_parent_item ( id) ;
11421182 if parent == id { return None }
11431183 id = parent;
11441184 }
@@ -1154,35 +1194,21 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> {
11541194
11551195 // We are looking at some node `n` with a given name and parent
11561196 // id; do their names match what I am seeking?
1157- fn matches_names ( & self , parent_of_n : NodeId , name : Name ) -> bool {
1197+ fn matches_names ( & self , parent_of_n : HirId , name : Name ) -> bool {
11581198 name == & * * self . item_name && self . suffix_matches ( parent_of_n)
11591199 }
1160- }
11611200
1162- impl < ' a , ' hir > Iterator for NodesMatchingSuffix < ' a , ' hir > {
1163- type Item = NodeId ;
1164-
1165- fn next ( & mut self ) -> Option < NodeId > {
1166- loop {
1167- let idx = self . idx ;
1168- if idx. as_usize ( ) >= self . map . entry_count ( ) {
1169- return None ;
1170- }
1171- self . idx = NodeId :: from_u32 ( self . idx . as_u32 ( ) + 1 ) ;
1172- let hir_idx = self . map . node_to_hir_id ( idx) ;
1173- let name = match self . map . find_entry ( hir_idx) . map ( |entry| entry. node ) {
1174- Some ( Node :: Item ( n) ) => n. name ( ) ,
1175- Some ( Node :: ForeignItem ( n) ) => n. name ( ) ,
1176- Some ( Node :: TraitItem ( n) ) => n. name ( ) ,
1177- Some ( Node :: ImplItem ( n) ) => n. name ( ) ,
1178- Some ( Node :: Variant ( n) ) => n. name ( ) ,
1179- Some ( Node :: Field ( n) ) => n. name ( ) ,
1180- _ => continue ,
1181- } ;
1182- if self . matches_names ( self . map . get_parent ( idx) , name) {
1183- return Some ( idx)
1184- }
1185- }
1201+ fn matces_suffix ( & self , hir : HirId ) -> bool {
1202+ let name = match self . map . find_entry ( hir) . map ( |entry| entry. node ) {
1203+ Some ( Node :: Item ( n) ) => n. name ( ) ,
1204+ Some ( Node :: ForeignItem ( n) ) => n. name ( ) ,
1205+ Some ( Node :: TraitItem ( n) ) => n. name ( ) ,
1206+ Some ( Node :: ImplItem ( n) ) => n. name ( ) ,
1207+ Some ( Node :: Variant ( n) ) => n. name ( ) ,
1208+ Some ( Node :: Field ( n) ) => n. name ( ) ,
1209+ _ => return false ,
1210+ } ;
1211+ self . matches_names ( self . map . get_parent_item ( hir) , name)
11861212 }
11871213}
11881214
0 commit comments