@@ -61,7 +61,7 @@ pub struct FirstSegmentUnresolved {
61
61
}
62
62
63
63
/// A name that will be used during item lookups.
64
- #[ derive( Debug ) ]
64
+ #[ derive( Debug , Clone ) ]
65
65
pub enum NameToImport {
66
66
/// Requires items with names that exactly match the given string, case-sensitive.
67
67
Exact ( String ) ,
@@ -201,131 +201,96 @@ impl ImportAssets {
201
201
sema : & Semantics < RootDatabase > ,
202
202
prefixed : Option < PrefixKind > ,
203
203
) -> Vec < LocatedImport > {
204
- let items_with_candidate_name = match self . name_to_import ( ) {
205
- NameToImport :: Exact ( exact_name) => items_locator:: with_exact_name (
206
- sema,
207
- self . module_with_candidate . krate ( ) ,
208
- exact_name. clone ( ) ,
209
- ) ,
210
- // FIXME: ideally, we should avoid using `fst` for seacrhing trait imports for assoc items:
211
- // instead, we need to look up all trait impls for a certain struct and search through them only
212
- // see https://github.com/rust-analyzer/rust-analyzer/pull/7293#issuecomment-761585032
213
- // and https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Blanket.20trait.20impls.20lookup
214
- // for the details
215
- NameToImport :: Fuzzy ( fuzzy_name) => {
216
- let ( assoc_item_search, limit) = if self . import_candidate . is_trait_candidate ( ) {
217
- ( AssocItemSearch :: AssocItemsOnly , None )
218
- } else {
219
- ( AssocItemSearch :: Include , Some ( DEFAULT_QUERY_SEARCH_LIMIT ) )
220
- } ;
221
-
222
- items_locator:: with_similar_name (
223
- sema,
224
- self . module_with_candidate . krate ( ) ,
225
- fuzzy_name. clone ( ) ,
226
- assoc_item_search,
227
- limit,
228
- )
229
- }
230
- } ;
204
+ let _p = profile:: span ( "import_assets::search_for" ) ;
231
205
232
206
let scope_definitions = self . scope_definitions ( sema) ;
233
- self . applicable_defs ( sema. db , prefixed, items_with_candidate_name)
234
- . into_iter ( )
235
- . filter ( |import| import. import_path . len ( ) > 1 )
236
- . filter ( |import| !scope_definitions. contains ( & ScopeDef :: from ( import. item_to_import ) ) )
237
- . sorted_by_key ( |import| import. import_path . clone ( ) )
238
- . collect ( )
239
- }
240
-
241
- fn scope_definitions ( & self , sema : & Semantics < RootDatabase > ) -> FxHashSet < ScopeDef > {
242
- let mut scope_definitions = FxHashSet :: default ( ) ;
243
- sema. scope ( & self . candidate_node ) . process_all_names ( & mut |_, scope_def| {
244
- scope_definitions. insert ( scope_def) ;
245
- } ) ;
246
- scope_definitions
247
- }
248
-
249
- fn name_to_import ( & self ) -> & NameToImport {
250
- match & self . import_candidate {
251
- ImportCandidate :: Path ( candidate) => & candidate. name ,
252
- ImportCandidate :: TraitAssocItem ( candidate)
253
- | ImportCandidate :: TraitMethod ( candidate) => & candidate. assoc_item_name ,
254
- }
255
- }
256
-
257
- fn applicable_defs (
258
- & self ,
259
- db : & RootDatabase ,
260
- prefixed : Option < PrefixKind > ,
261
- items_with_candidate_name : FxHashSet < ItemInNs > ,
262
- ) -> FxHashSet < LocatedImport > {
263
- let _p = profile:: span ( "import_assets::applicable_defs" ) ;
264
207
let current_crate = self . module_with_candidate . krate ( ) ;
265
-
266
208
let mod_path = |item| {
267
- get_mod_path ( db, item_for_path_search ( db, item) ?, & self . module_with_candidate , prefixed)
209
+ get_mod_path (
210
+ sema. db ,
211
+ item_for_path_search ( sema. db , item) ?,
212
+ & self . module_with_candidate ,
213
+ prefixed,
214
+ )
268
215
} ;
269
216
270
217
match & self . import_candidate {
271
218
ImportCandidate :: Path ( path_candidate) => {
272
- path_applicable_imports ( db, path_candidate, mod_path, items_with_candidate_name)
219
+ path_applicable_imports ( sema, current_crate, path_candidate, mod_path)
220
+ }
221
+ ImportCandidate :: TraitAssocItem ( trait_candidate) => {
222
+ trait_applicable_items ( sema, current_crate, trait_candidate, true , mod_path)
223
+ }
224
+ ImportCandidate :: TraitMethod ( trait_candidate) => {
225
+ trait_applicable_items ( sema, current_crate, trait_candidate, false , mod_path)
273
226
}
274
- ImportCandidate :: TraitAssocItem ( trait_candidate) => trait_applicable_items (
275
- db,
276
- current_crate,
277
- trait_candidate,
278
- true ,
279
- mod_path,
280
- items_with_candidate_name,
281
- ) ,
282
- ImportCandidate :: TraitMethod ( trait_candidate) => trait_applicable_items (
283
- db,
284
- current_crate,
285
- trait_candidate,
286
- false ,
287
- mod_path,
288
- items_with_candidate_name,
289
- ) ,
290
227
}
228
+ . into_iter ( )
229
+ . filter ( |import| import. import_path . len ( ) > 1 )
230
+ . filter ( |import| !scope_definitions. contains ( & ScopeDef :: from ( import. item_to_import ) ) )
231
+ . sorted_by_key ( |import| import. import_path . clone ( ) )
232
+ . collect ( )
233
+ }
234
+
235
+ fn scope_definitions ( & self , sema : & Semantics < RootDatabase > ) -> FxHashSet < ScopeDef > {
236
+ let _p = profile:: span ( "import_assets::scope_definitions" ) ;
237
+ let mut scope_definitions = FxHashSet :: default ( ) ;
238
+ sema. scope ( & self . candidate_node ) . process_all_names ( & mut |_, scope_def| {
239
+ scope_definitions. insert ( scope_def) ;
240
+ } ) ;
241
+ scope_definitions
291
242
}
292
243
}
293
244
294
245
fn path_applicable_imports (
295
- db : & RootDatabase ,
246
+ sema : & Semantics < RootDatabase > ,
247
+ current_crate : Crate ,
296
248
path_candidate : & PathImportCandidate ,
297
249
mod_path : impl Fn ( ItemInNs ) -> Option < ModPath > + Copy ,
298
- items_with_candidate_name : FxHashSet < ItemInNs > ,
299
250
) -> FxHashSet < LocatedImport > {
300
251
let _p = profile:: span ( "import_assets::path_applicable_imports" ) ;
301
252
302
- let ( unresolved_first_segment , unresolved_qualifier ) = match & path_candidate. qualifier {
253
+ match & path_candidate. qualifier {
303
254
None => {
304
- return items_with_candidate_name
305
- . into_iter ( )
306
- . filter_map ( |item| {
307
- if item_as_assoc ( db, item) . is_some ( ) {
308
- // unqualified assoc items are not valid syntax
309
- return None ;
310
- }
311
-
312
- let mod_path = mod_path ( item) ?;
313
- Some ( LocatedImport :: new ( mod_path. clone ( ) , item, item, Some ( mod_path) ) )
314
- } )
315
- . collect ( ) ;
255
+ items_locator:: locate_for_name (
256
+ sema,
257
+ current_crate,
258
+ path_candidate. name . clone ( ) ,
259
+ // unqualified assoc items are not valid syntax
260
+ AssocItemSearch :: Exclude ,
261
+ Some ( DEFAULT_QUERY_SEARCH_LIMIT ) ,
262
+ )
263
+ . into_iter ( )
264
+ . filter_map ( |item| {
265
+ let mod_path = mod_path ( item) ?;
266
+ Some ( LocatedImport :: new ( mod_path. clone ( ) , item, item, Some ( mod_path) ) )
267
+ } )
268
+ . collect ( )
316
269
}
317
- Some ( first_segment_unresolved) => (
318
- first_segment_unresolved. fist_segment . to_string ( ) ,
319
- path_to_string_stripping_turbo_fish ( & first_segment_unresolved. full_qualifier ) ,
320
- ) ,
321
- } ;
322
-
323
- items_with_candidate_name
324
- . into_iter ( )
325
- . filter_map ( |item| {
326
- import_for_item ( db, mod_path, & unresolved_first_segment, & unresolved_qualifier, item)
327
- } )
328
- . collect ( )
270
+ Some ( first_segment_unresolved) => {
271
+ let unresolved_qualifier =
272
+ path_to_string_stripping_turbo_fish ( & first_segment_unresolved. full_qualifier ) ;
273
+ let unresolved_first_segment = first_segment_unresolved. fist_segment . text ( ) ;
274
+ items_locator:: locate_for_name (
275
+ sema,
276
+ current_crate,
277
+ path_candidate. name . clone ( ) ,
278
+ AssocItemSearch :: Include ,
279
+ Some ( DEFAULT_QUERY_SEARCH_LIMIT ) ,
280
+ )
281
+ . into_iter ( )
282
+ . filter_map ( |item| {
283
+ import_for_item (
284
+ sema. db ,
285
+ mod_path,
286
+ unresolved_first_segment,
287
+ & unresolved_qualifier,
288
+ item,
289
+ )
290
+ } )
291
+ . collect ( )
292
+ }
293
+ }
329
294
}
330
295
331
296
fn import_for_item (
@@ -440,25 +405,32 @@ fn module_with_segment_name(
440
405
}
441
406
442
407
fn trait_applicable_items (
443
- db : & RootDatabase ,
408
+ sema : & Semantics < RootDatabase > ,
444
409
current_crate : Crate ,
445
410
trait_candidate : & TraitImportCandidate ,
446
411
trait_assoc_item : bool ,
447
412
mod_path : impl Fn ( ItemInNs ) -> Option < ModPath > ,
448
- items_with_candidate_name : FxHashSet < ItemInNs > ,
449
413
) -> FxHashSet < LocatedImport > {
450
414
let _p = profile:: span ( "import_assets::trait_applicable_items" ) ;
451
- let mut required_assoc_items = FxHashSet :: default ( ) ;
452
415
453
- let trait_candidates = items_with_candidate_name
454
- . into_iter ( )
455
- . filter_map ( |input| item_as_assoc ( db, input) )
456
- . filter_map ( |assoc| {
457
- let assoc_item_trait = assoc. containing_trait ( db) ?;
458
- required_assoc_items. insert ( assoc) ;
459
- Some ( assoc_item_trait. into ( ) )
460
- } )
461
- . collect ( ) ;
416
+ let db = sema. db ;
417
+
418
+ let mut required_assoc_items = FxHashSet :: default ( ) ;
419
+ let trait_candidates = items_locator:: locate_for_name (
420
+ sema,
421
+ current_crate,
422
+ trait_candidate. assoc_item_name . clone ( ) ,
423
+ AssocItemSearch :: AssocItemsOnly ,
424
+ Some ( DEFAULT_QUERY_SEARCH_LIMIT ) ,
425
+ )
426
+ . into_iter ( )
427
+ . filter_map ( |input| item_as_assoc ( db, input) )
428
+ . filter_map ( |assoc| {
429
+ let assoc_item_trait = assoc. containing_trait ( db) ?;
430
+ required_assoc_items. insert ( assoc) ;
431
+ Some ( assoc_item_trait. into ( ) )
432
+ } )
433
+ . collect ( ) ;
462
434
463
435
let mut located_imports = FxHashSet :: default ( ) ;
464
436
@@ -567,10 +539,6 @@ impl ImportCandidate {
567
539
) -> Option < Self > {
568
540
path_import_candidate ( sema, qualifier, NameToImport :: Fuzzy ( fuzzy_name) )
569
541
}
570
-
571
- fn is_trait_candidate ( & self ) -> bool {
572
- matches ! ( self , ImportCandidate :: TraitAssocItem ( _) | ImportCandidate :: TraitMethod ( _) )
573
- }
574
542
}
575
543
576
544
fn path_import_candidate (
0 commit comments