@@ -61,7 +61,7 @@ pub struct FirstSegmentUnresolved {
6161}
6262
6363/// A name that will be used during item lookups.
64- #[ derive( Debug ) ]
64+ #[ derive( Debug , Clone ) ]
6565pub enum NameToImport {
6666 /// Requires items with names that exactly match the given string, case-sensitive.
6767 Exact ( String ) ,
@@ -201,131 +201,96 @@ impl ImportAssets {
201201 sema : & Semantics < RootDatabase > ,
202202 prefixed : Option < PrefixKind > ,
203203 ) -> 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" ) ;
231205
232206 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" ) ;
264207 let current_crate = self . module_with_candidate . krate ( ) ;
265-
266208 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+ )
268215 } ;
269216
270217 match & self . import_candidate {
271218 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)
273226 }
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- ) ,
290227 }
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
291242 }
292243}
293244
294245fn path_applicable_imports (
295- db : & RootDatabase ,
246+ sema : & Semantics < RootDatabase > ,
247+ current_crate : Crate ,
296248 path_candidate : & PathImportCandidate ,
297249 mod_path : impl Fn ( ItemInNs ) -> Option < ModPath > + Copy ,
298- items_with_candidate_name : FxHashSet < ItemInNs > ,
299250) -> FxHashSet < LocatedImport > {
300251 let _p = profile:: span ( "import_assets::path_applicable_imports" ) ;
301252
302- let ( unresolved_first_segment , unresolved_qualifier ) = match & path_candidate. qualifier {
253+ match & path_candidate. qualifier {
303254 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 ( )
316269 }
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+ }
329294}
330295
331296fn import_for_item (
@@ -440,25 +405,32 @@ fn module_with_segment_name(
440405}
441406
442407fn trait_applicable_items (
443- db : & RootDatabase ,
408+ sema : & Semantics < RootDatabase > ,
444409 current_crate : Crate ,
445410 trait_candidate : & TraitImportCandidate ,
446411 trait_assoc_item : bool ,
447412 mod_path : impl Fn ( ItemInNs ) -> Option < ModPath > ,
448- items_with_candidate_name : FxHashSet < ItemInNs > ,
449413) -> FxHashSet < LocatedImport > {
450414 let _p = profile:: span ( "import_assets::trait_applicable_items" ) ;
451- let mut required_assoc_items = FxHashSet :: default ( ) ;
452415
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 ( ) ;
462434
463435 let mut located_imports = FxHashSet :: default ( ) ;
464436
@@ -567,10 +539,6 @@ impl ImportCandidate {
567539 ) -> Option < Self > {
568540 path_import_candidate ( sema, qualifier, NameToImport :: Fuzzy ( fuzzy_name) )
569541 }
570-
571- fn is_trait_candidate ( & self ) -> bool {
572- matches ! ( self , ImportCandidate :: TraitAssocItem ( _) | ImportCandidate :: TraitMethod ( _) )
573- }
574542}
575543
576544fn path_import_candidate (
0 commit comments