@@ -22,7 +22,7 @@ use crate::{
2222type FxIndexMap < K , V > = IndexMap < K , V , BuildHasherDefault < FxHasher > > ;
2323
2424/// Item import details stored in the `ImportMap`.
25- #[ derive( Debug , Clone , Eq , PartialEq ) ]
25+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
2626pub struct ImportInfo {
2727 /// A name that can be used to import the item, relative to the crate's root.
2828 pub name : Name ,
@@ -78,7 +78,8 @@ impl ImportMap {
7878
7979 // Build the FST, taking care not to insert duplicate values.
8080 let mut builder = fst:: MapBuilder :: memory ( ) ;
81- let iter = importables. iter ( ) . enumerate ( ) . dedup_by ( |lhs, rhs| lhs. 1 . 1 == rhs. 1 . 1 ) ;
81+ let iter =
82+ importables. iter ( ) . enumerate ( ) . dedup_by ( |( _, ( _, lhs) ) , ( _, ( _, rhs) ) | lhs == rhs) ;
8283 for ( start_idx, ( _, name) ) in iter {
8384 let _ = builder. insert ( name, start_idx as u64 ) ;
8485 }
@@ -128,7 +129,6 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
128129 }
129130 } ) ;
130131
131- // FIXME: This loop might add the same entry up to 3 times per item! dedup
132132 for ( name, per_ns) in visible_items {
133133 for ( item, import) in per_ns. iter_items ( ) {
134134 let attr_id = if let Some ( import) = import {
@@ -164,10 +164,10 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
164164 ) ;
165165 }
166166
167- map . entry ( item )
168- . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: No ) )
169- . 0
170- . push ( import_info) ;
167+ let ( infos , _ ) =
168+ map . entry ( item ) . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: No ) ) ;
169+ infos . reserve_exact ( 1 ) ;
170+ infos . push ( import_info) ;
171171
172172 // If we've just added a module, descend into it.
173173 if let Some ( ModuleDefId :: ModuleId ( mod_id) ) = item. as_module_def_id ( ) {
@@ -213,10 +213,10 @@ fn collect_trait_assoc_items(
213213 is_unstable : attrs. is_unstable ( ) ,
214214 } ;
215215
216- map . entry ( assoc_item )
217- . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: Yes ) )
218- . 0
219- . push ( assoc_item_info) ;
216+ let ( infos , _ ) =
217+ map . entry ( assoc_item ) . or_insert_with ( || ( SmallVec :: new ( ) , IsTraitAssocItem :: Yes ) ) ;
218+ infos . reserve_exact ( 1 ) ;
219+ infos . push ( assoc_item_info) ;
220220 }
221221}
222222
@@ -234,10 +234,13 @@ impl fmt::Debug for ImportMap {
234234 let mut importable_names: Vec < _ > = self
235235 . map
236236 . iter ( )
237- . map ( |( item, _) | match item {
238- ItemInNs :: Types ( it) => format ! ( "- {it:?} (t)" , ) ,
239- ItemInNs :: Values ( it) => format ! ( "- {it:?} (v)" , ) ,
240- ItemInNs :: Macros ( it) => format ! ( "- {it:?} (m)" , ) ,
237+ . map ( |( item, ( infos, _) ) | {
238+ let l = infos. len ( ) ;
239+ match item {
240+ ItemInNs :: Types ( it) => format ! ( "- {it:?} (t) [{l}]" , ) ,
241+ ItemInNs :: Values ( it) => format ! ( "- {it:?} (v) [{l}]" , ) ,
242+ ItemInNs :: Macros ( it) => format ! ( "- {it:?} (m) [{l}]" , ) ,
243+ }
241244 } )
242245 . collect ( ) ;
243246
@@ -368,7 +371,7 @@ impl Query {
368371pub fn search_dependencies (
369372 db : & dyn DefDatabase ,
370373 krate : CrateId ,
371- query : Query ,
374+ ref query: Query ,
372375) -> FxHashSet < ItemInNs > {
373376 let _p = profile:: span ( "search_dependencies" ) . detail ( || format ! ( "{query:?}" ) ) ;
374377
@@ -386,6 +389,7 @@ pub fn search_dependencies(
386389 let mut stream = op. union ( ) ;
387390
388391 let mut res = FxHashSet :: default ( ) ;
392+ let mut common_importable_data_scratch = vec ! [ ] ;
389393 while let Some ( ( _, indexed_values) ) = stream. next ( ) {
390394 for & IndexedValue { index, value } in indexed_values {
391395 let import_map = & import_maps[ index] ;
@@ -398,36 +402,45 @@ pub fn search_dependencies(
398402 continue ;
399403 }
400404
401- // FIXME: We probably need to account for other possible matches in this alias group?
402- let Some ( common_importable_data) =
403- importable_data. iter ( ) . find ( |& info| query. import_matches ( db, info, true ) )
404- else {
405+ common_importable_data_scratch. extend (
406+ importable_data
407+ . iter ( )
408+ . filter ( |& info| query. import_matches ( db, info, true ) )
409+ // Name shared by the importable items in this group.
410+ . map ( |info| info. name . to_smol_str ( ) ) ,
411+ ) ;
412+ if common_importable_data_scratch. is_empty ( ) {
405413 continue ;
406- } ;
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
414+ }
415+ common_importable_data_scratch. sort ( ) ;
416+ common_importable_data_scratch. dedup ( ) ;
417+
418+ let iter =
419+ common_importable_data_scratch. drain ( ..) . flat_map ( |common_importable_name| {
420+ // Add the items from this name group. Those are all subsequent items in
421+ // `importables` whose name match `common_importable_name`.
422+ importables
423+ . iter ( )
424+ . copied ( )
425+ . take_while ( move |item| {
426+ let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
427+ query. matches_assoc_mode ( assoc_mode)
428+ && import_infos. iter ( ) . any ( |info| {
429+ info. name
430+ . to_smol_str ( )
431+ . eq_ignore_ascii_case ( & common_importable_name)
432+ } )
433+ } )
434+ . filter ( move |item| {
435+ !query. case_sensitive || {
436+ // we've already checked the common importables name case-insensitively
437+ let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
438+ query. matches_assoc_mode ( assoc_mode)
439+ && import_infos
440+ . iter ( )
441+ . any ( |info| query. import_matches ( db, info, false ) )
442+ }
422443 } )
423- } )
424- . filter ( |item| {
425- !query. case_sensitive || {
426- // we've already checked the common importables name case-insensitively
427- let & ( ref import_infos, assoc_mode) = & import_map. map [ item] ;
428- query. matches_assoc_mode ( assoc_mode)
429- && import_infos. iter ( ) . any ( |info| query. import_matches ( db, info, false ) )
430- }
431444 } ) ;
432445 res. extend ( iter) ;
433446
0 commit comments