@@ -22,7 +22,7 @@ use crate::{
22
22
type FxIndexMap < K , V > = IndexMap < K , V , BuildHasherDefault < FxHasher > > ;
23
23
24
24
/// Item import details stored in the `ImportMap`.
25
- #[ derive( Debug , Clone , Eq , PartialEq ) ]
25
+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
26
26
pub struct ImportInfo {
27
27
/// A name that can be used to import the item, relative to the crate's root.
28
28
pub name : Name ,
@@ -78,7 +78,8 @@ impl ImportMap {
78
78
79
79
// Build the FST, taking care not to insert duplicate values.
80
80
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) ;
82
83
for ( start_idx, ( _, name) ) in iter {
83
84
let _ = builder. insert ( name, start_idx as u64 ) ;
84
85
}
@@ -128,7 +129,6 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
128
129
}
129
130
} ) ;
130
131
131
- // FIXME: This loop might add the same entry up to 3 times per item! dedup
132
132
for ( name, per_ns) in visible_items {
133
133
for ( item, import) in per_ns. iter_items ( ) {
134
134
let attr_id = if let Some ( import) = import {
@@ -164,10 +164,10 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
164
164
) ;
165
165
}
166
166
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) ;
171
171
172
172
// If we've just added a module, descend into it.
173
173
if let Some ( ModuleDefId :: ModuleId ( mod_id) ) = item. as_module_def_id ( ) {
@@ -213,10 +213,10 @@ fn collect_trait_assoc_items(
213
213
is_unstable : attrs. is_unstable ( ) ,
214
214
} ;
215
215
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) ;
220
220
}
221
221
}
222
222
@@ -234,10 +234,13 @@ impl fmt::Debug for ImportMap {
234
234
let mut importable_names: Vec < _ > = self
235
235
. map
236
236
. 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
+ }
241
244
} )
242
245
. collect ( ) ;
243
246
@@ -368,7 +371,7 @@ impl Query {
368
371
pub fn search_dependencies (
369
372
db : & dyn DefDatabase ,
370
373
krate : CrateId ,
371
- query : Query ,
374
+ ref query: Query ,
372
375
) -> FxHashSet < ItemInNs > {
373
376
let _p = profile:: span ( "search_dependencies" ) . detail ( || format ! ( "{query:?}" ) ) ;
374
377
@@ -386,6 +389,7 @@ pub fn search_dependencies(
386
389
let mut stream = op. union ( ) ;
387
390
388
391
let mut res = FxHashSet :: default ( ) ;
392
+ let mut common_importable_data_scratch = vec ! [ ] ;
389
393
while let Some ( ( _, indexed_values) ) = stream. next ( ) {
390
394
for & IndexedValue { index, value } in indexed_values {
391
395
let import_map = & import_maps[ index] ;
@@ -398,36 +402,45 @@ pub fn search_dependencies(
398
402
continue ;
399
403
}
400
404
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 ( ) {
405
413
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
+ }
422
443
} )
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
- }
431
444
} ) ;
432
445
res. extend ( iter) ;
433
446
0 commit comments