@@ -11,6 +11,7 @@ use crate::middle::cstore::CrateStoreDyn;
11
11
12
12
use rustc_target:: spec:: abi:: Abi ;
13
13
use rustc_data_structures:: svh:: Svh ;
14
+ use rustc_data_structures:: indexed_vec:: IndexVec ;
14
15
use syntax:: ast:: { self , Name , NodeId } ;
15
16
use syntax:: source_map:: Spanned ;
16
17
use syntax:: ext:: base:: MacroKind ;
@@ -161,6 +162,13 @@ impl Forest {
161
162
}
162
163
}
163
164
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
+
164
172
/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
165
173
#[ derive( Clone ) ]
166
174
pub struct Map < ' hir > {
@@ -174,7 +182,7 @@ pub struct Map<'hir> {
174
182
/// The SVH of the local crate.
175
183
pub crate_hash : Svh ,
176
184
177
- map : FxHashMap < HirId , Entry < ' hir > > ,
185
+ map : HirEntryMap < ' hir > ,
178
186
179
187
definitions : & ' hir Definitions ,
180
188
@@ -183,6 +191,12 @@ pub struct Map<'hir> {
183
191
}
184
192
185
193
impl < ' 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
+
186
200
/// Registers a read in the dependency graph of the AST node with
187
201
/// the given `id`. This needs to be called each time a public
188
202
/// function returns the HIR for a node -- in other words, when it
@@ -191,7 +205,7 @@ impl<'hir> Map<'hir> {
191
205
/// read recorded). If the function just returns a DefId or
192
206
/// NodeId, no actual content was returned, so no read is needed.
193
207
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) {
195
209
self . dep_graph . read_index ( entry. dep_node ) ;
196
210
} else {
197
211
bug ! ( "called `HirMap::read()` with invalid `HirId`: {:?}" , hir_id)
@@ -378,12 +392,8 @@ impl<'hir> Map<'hir> {
378
392
} )
379
393
}
380
394
381
- fn entry_count ( & self ) -> usize {
382
- self . map . len ( )
383
- }
384
-
385
395
fn find_entry ( & self , id : HirId ) -> Option < Entry < ' hir > > {
386
- self . map . get ( & id) . cloned ( )
396
+ self . lookup ( id) . cloned ( )
387
397
}
388
398
389
399
pub fn krate ( & self ) -> & ' hir Crate {
@@ -433,7 +443,7 @@ impl<'hir> Map<'hir> {
433
443
/// item (possibly associated), a closure, or a `hir::AnonConst`.
434
444
pub fn body_owner ( & self , BodyId { hir_id } : BodyId ) -> NodeId {
435
445
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) ) ) ;
437
447
self . hir_to_node_id ( parent)
438
448
}
439
449
@@ -1004,6 +1014,34 @@ impl<'hir> Map<'hir> {
1004
1014
attrs. unwrap_or ( & [ ] )
1005
1015
}
1006
1016
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
+
1007
1045
/// Returns an iterator that yields the node id's with paths that
1008
1046
/// match `parts`. (Requires `parts` is non-empty.)
1009
1047
///
@@ -1012,13 +1050,16 @@ impl<'hir> Map<'hir> {
1012
1050
/// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
1013
1051
/// any other such items it can find in the map.
1014
1052
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 {
1017
1055
map : self ,
1018
1056
item_name : parts. last ( ) . unwrap ( ) ,
1019
1057
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
+ } )
1022
1063
}
1023
1064
1024
1065
pub fn span ( & self , id : NodeId ) -> Span {
@@ -1097,21 +1138,20 @@ impl<'hir> Map<'hir> {
1097
1138
}
1098
1139
}
1099
1140
1100
- pub struct NodesMatchingSuffix < ' a , ' hir : ' a > {
1101
- map : & ' a Map < ' hir > ,
1141
+ pub struct NodesMatchingSuffix < ' a > {
1142
+ map : & ' a Map < ' a > ,
1102
1143
item_name : & ' a String ,
1103
1144
in_which : & ' a [ String ] ,
1104
- idx : NodeId ,
1105
1145
}
1106
1146
1107
- impl < ' a , ' hir > NodesMatchingSuffix < ' a , ' hir > {
1147
+ impl < ' a > NodesMatchingSuffix < ' a > {
1108
1148
/// Returns `true` only if some suffix of the module path for parent
1109
1149
/// matches `self.in_which`.
1110
1150
///
1111
1151
/// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
1112
1152
/// returns true if parent's path ends with the suffix
1113
1153
/// `x_0::x_1::...::x_k`.
1114
- fn suffix_matches ( & self , parent : NodeId ) -> bool {
1154
+ fn suffix_matches ( & self , parent : HirId ) -> bool {
1115
1155
let mut cursor = parent;
1116
1156
for part in self . in_which . iter ( ) . rev ( ) {
1117
1157
let ( mod_id, mod_name) = match find_first_mod_parent ( self . map , cursor) {
@@ -1121,7 +1161,7 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> {
1121
1161
if mod_name != & * * part {
1122
1162
return false ;
1123
1163
}
1124
- cursor = self . map . get_parent ( mod_id) ;
1164
+ cursor = self . map . get_parent_item ( mod_id) ;
1125
1165
}
1126
1166
return true ;
1127
1167
@@ -1131,14 +1171,14 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> {
1131
1171
// If `id` itself is a mod named `m` with parent `p`, then
1132
1172
// returns `Some(id, m, p)`. If `id` has no mod in its parent
1133
1173
// 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 ) > {
1135
1175
loop {
1136
- if let Node :: Item ( item) = map. find ( id) ? {
1176
+ if let Node :: Item ( item) = map. find_by_hir_id ( id) ? {
1137
1177
if item_is_mod ( & item) {
1138
1178
return Some ( ( id, item. ident . name ) )
1139
1179
}
1140
1180
}
1141
- let parent = map. get_parent ( id) ;
1181
+ let parent = map. get_parent_item ( id) ;
1142
1182
if parent == id { return None }
1143
1183
id = parent;
1144
1184
}
@@ -1154,35 +1194,21 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> {
1154
1194
1155
1195
// We are looking at some node `n` with a given name and parent
1156
1196
// 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 {
1158
1198
name == & * * self . item_name && self . suffix_matches ( parent_of_n)
1159
1199
}
1160
- }
1161
1200
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)
1186
1212
}
1187
1213
}
1188
1214
0 commit comments