11//! A map of all publicly exported items in a crate.
22
3- use std:: { collections :: hash_map :: Entry , fmt, hash:: BuildHasherDefault } ;
3+ use std:: { fmt, hash:: BuildHasherDefault } ;
44
55use base_db:: CrateId ;
66use fst:: { self , raw:: IndexedValue , Streamer } ;
77use hir_expand:: name:: Name ;
88use indexmap:: IndexMap ;
99use itertools:: Itertools ;
10- use rustc_hash:: { FxHashMap , FxHashSet , FxHasher } ;
11- use smallvec:: { smallvec , SmallVec } ;
10+ use rustc_hash:: { FxHashSet , FxHasher } ;
11+ use smallvec:: SmallVec ;
1212use triomphe:: Arc ;
1313
1414use crate :: {
@@ -103,11 +103,13 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
103103
104104 // We look only into modules that are public(ly reexported), starting with the crate root.
105105 let root = def_map. module_id ( DefMap :: ROOT ) ;
106- let mut worklist = vec ! [ ( root, 0u32 ) ] ;
107- // Records items' minimum module depth.
108- let mut depth_map = FxHashMap :: default ( ) ;
106+ let mut worklist = vec ! [ root] ;
107+ let mut visited = FxHashSet :: default ( ) ;
109108
110- while let Some ( ( module, depth) ) = worklist. pop ( ) {
109+ while let Some ( module) = worklist. pop ( ) {
110+ if !visited. insert ( module) {
111+ continue ;
112+ }
111113 let ext_def_map;
112114 let mod_data = if module. krate == krate {
113115 & def_map[ module. local_id ]
@@ -126,6 +128,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
126128 }
127129 } ) ;
128130
131+ // FIXME: This loop might add the same entry up to 3 times per item! dedup
129132 for ( name, per_ns) in visible_items {
130133 for ( item, import) in per_ns. iter_items ( ) {
131134 let attr_id = if let Some ( import) = import {
@@ -139,11 +142,10 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
139142 ItemInNs :: Macros ( id) => Some ( id. into ( ) ) ,
140143 }
141144 } ;
142- let status @ ( is_doc_hidden, is_unstable) =
143- attr_id. map_or ( ( false , false ) , |attr_id| {
144- let attrs = db. attrs ( attr_id) ;
145- ( attrs. has_doc_hidden ( ) , attrs. is_unstable ( ) )
146- } ) ;
145+ let ( is_doc_hidden, is_unstable) = attr_id. map_or ( ( false , false ) , |attr_id| {
146+ let attrs = db. attrs ( attr_id) ;
147+ ( attrs. has_doc_hidden ( ) , attrs. is_unstable ( ) )
148+ } ) ;
147149
148150 let import_info = ImportInfo {
149151 name : name. clone ( ) ,
@@ -152,50 +154,6 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
152154 is_unstable,
153155 } ;
154156
155- match depth_map. entry ( item) {
156- Entry :: Vacant ( entry) => _ = entry. insert ( ( depth, status) ) ,
157- Entry :: Occupied ( mut entry) => {
158- let & ( occ_depth, ( occ_is_doc_hidden, occ_is_unstable) ) = entry. get ( ) ;
159- ( depth, occ_depth) ;
160- let overwrite = match (
161- is_doc_hidden,
162- occ_is_doc_hidden,
163- is_unstable,
164- occ_is_unstable,
165- ) {
166- // no change of hiddeness or unstableness
167- ( true , true , true , true )
168- | ( true , true , false , false )
169- | ( false , false , true , true )
170- | ( false , false , false , false ) => depth < occ_depth,
171-
172- // either less hidden or less unstable, accept
173- ( true , true , false , true )
174- | ( false , true , true , true )
175- | ( false , true , false , true )
176- | ( false , true , false , false )
177- | ( false , false , false , true ) => true ,
178- // more hidden or unstable, discard
179- ( true , true , true , false )
180- | ( true , false , true , true )
181- | ( true , false , true , false )
182- | ( true , false , false , false )
183- | ( false , false , true , false ) => false ,
184-
185- // exchanges doc(hidden) for unstable (and vice-versa),
186- ( true , false , false , true ) | ( false , true , true , false ) => {
187- depth < occ_depth
188- }
189- } ;
190- // FIXME: Remove the overwrite rules as we can now record exports and
191- // aliases for the same item
192- if !overwrite {
193- continue ;
194- }
195- entry. insert ( ( depth, status) ) ;
196- }
197- }
198-
199157 if let Some ( ModuleDefId :: TraitId ( tr) ) = item. as_module_def_id ( ) {
200158 collect_trait_assoc_items (
201159 db,
@@ -206,13 +164,14 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
206164 ) ;
207165 }
208166
209- map. insert ( item, ( smallvec ! [ import_info] , IsTraitAssocItem :: No ) ) ;
167+ map. entry ( item)
168+ . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: No ) )
169+ . 0
170+ . push ( import_info) ;
210171
211- // If we've just added a module, descend into it. We might traverse modules
212- // multiple times, but only if the module depth is smaller (else we `continue`
213- // above).
172+ // If we've just added a module, descend into it.
214173 if let Some ( ModuleDefId :: ModuleId ( mod_id) ) = item. as_module_def_id ( ) {
215- worklist. push ( ( mod_id, depth + 1 ) ) ;
174+ worklist. push ( mod_id) ;
216175 }
217176 }
218177 }
@@ -253,7 +212,11 @@ fn collect_trait_assoc_items(
253212 is_doc_hidden : attrs. has_doc_hidden ( ) ,
254213 is_unstable : attrs. is_unstable ( ) ,
255214 } ;
256- map. insert ( assoc_item, ( smallvec ! [ assoc_item_info] , IsTraitAssocItem :: Yes ) ) ;
215+
216+ map. entry ( assoc_item)
217+ . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: Yes ) )
218+ . 0
219+ . push ( assoc_item_info) ;
257220 }
258221}
259222
@@ -284,7 +247,7 @@ impl fmt::Debug for ImportMap {
284247}
285248
286249/// A way to match import map contents against the search query.
287- #[ derive( Debug ) ]
250+ #[ derive( Copy , Clone , Debug ) ]
288251enum SearchMode {
289252 /// Import map entry should strictly match the query string.
290253 Exact ,
@@ -426,7 +389,7 @@ pub fn search_dependencies(
426389 while let Some ( ( _, indexed_values) ) = stream. next ( ) {
427390 for & IndexedValue { index, value } in indexed_values {
428391 let import_map = & import_maps[ index] ;
429- let [ importable , importables @ ..] = & import_map. importables [ value as usize ..] else {
392+ let importables @ [ importable , ..] = & import_map. importables [ value as usize ..] else {
430393 continue ;
431394 } ;
432395
@@ -441,38 +404,32 @@ pub fn search_dependencies(
441404 else {
442405 continue ;
443406 } ;
444- res. insert ( * importable) ;
445-
446- if !importables. is_empty ( ) {
447- // FIXME: so many allocs...
448- // Name shared by the importable items in this group.
449- let common_importable_name =
450- common_importable_data. name . to_smol_str ( ) . to_ascii_lowercase ( ) ;
451- // Add the items from this name group. Those are all subsequent items in
452- // `importables` whose name match `common_importable_name`.
453- let iter = importables
454- . iter ( )
455- . copied ( )
456- . take_while ( |item| {
407+
408+ // FIXME: so many allocs...
409+ // Name shared by the importable items in this group.
410+ let common_importable_name =
411+ common_importable_data. name . to_smol_str ( ) . to_ascii_lowercase ( ) ;
412+ // Add the items from this name group. Those are all subsequent items in
413+ // `importables` whose name match `common_importable_name`.
414+ let iter = importables
415+ . iter ( )
416+ . copied ( )
417+ . take_while ( |item| {
418+ let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
419+ query. matches_assoc_mode ( assoc_mode)
420+ && import_infos. iter ( ) . any ( |info| {
421+ info. name . to_smol_str ( ) . to_ascii_lowercase ( ) == common_importable_name
422+ } )
423+ } )
424+ . filter ( |item| {
425+ !query. case_sensitive || {
426+ // we've already checked the common importables name case-insensitively
457427 let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
458428 query. matches_assoc_mode ( assoc_mode)
459- && import_infos. iter ( ) . any ( |info| {
460- info. name . to_smol_str ( ) . to_ascii_lowercase ( )
461- == common_importable_name
462- } )
463- } )
464- . filter ( |item| {
465- !query. case_sensitive || {
466- // we've already checked the common importables name case-insensitively
467- let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
468- query. matches_assoc_mode ( assoc_mode)
469- && import_infos
470- . iter ( )
471- . any ( |info| query. import_matches ( db, info, false ) )
472- }
473- } ) ;
474- res. extend ( iter) ;
475- }
429+ && import_infos. iter ( ) . any ( |info| query. import_matches ( db, info, false ) )
430+ }
431+ } ) ;
432+ res. extend ( iter) ;
476433
477434 if res. len ( ) >= query. limit {
478435 return res;
@@ -665,6 +622,7 @@ mod tests {
665622 main:
666623 - publ1 (t)
667624 - real_pu2 (t)
625+ - real_pu2::Pub (t)
668626 - real_pub (t)
669627 - real_pub::Pub (t)
670628 "# ] ] ,
@@ -690,6 +648,7 @@ mod tests {
690648 - sub (t)
691649 - sub::Def (t)
692650 - sub::subsub (t)
651+ - sub::subsub::Def (t)
693652 "# ] ] ,
694653 ) ;
695654 }
@@ -789,7 +748,9 @@ mod tests {
789748 - module (t)
790749 - module::S (t)
791750 - module::S (v)
751+ - module::module (t)
792752 - sub (t)
753+ - sub::module (t)
793754 "# ] ] ,
794755 ) ;
795756 }
0 commit comments