11//! Look up accessible paths for items.
22
3- use std:: ops:: ControlFlow ;
3+ use std:: { convert :: Infallible , ops:: ControlFlow } ;
44
55use hir:: {
66 AsAssocItem , AssocItem , AssocItemContainer , Complete , Crate , FindPathConfig , HasCrate ,
@@ -9,6 +9,7 @@ use hir::{
99} ;
1010use itertools:: Itertools ;
1111use rustc_hash:: { FxHashMap , FxHashSet } ;
12+ use smallvec:: SmallVec ;
1213use syntax:: {
1314 AstNode , SyntaxNode ,
1415 ast:: { self , HasName , make} ,
@@ -416,7 +417,7 @@ fn path_applicable_imports(
416417 NameToImport :: Exact ( first_qsegment. as_str ( ) . to_owned ( ) , true ) ,
417418 AssocSearchMode :: Exclude ,
418419 )
419- . filter_map ( |( item, do_not_complete) | {
420+ . flat_map ( |( item, do_not_complete) | {
420421 // we found imports for `first_qsegment`, now we need to filter these imports by whether
421422 // they result in resolving the rest of the path successfully
422423 validate_resolvable (
@@ -446,10 +447,10 @@ fn validate_resolvable(
446447 resolved_qualifier : ItemInNs ,
447448 unresolved_qualifier : & [ Name ] ,
448449 complete_in_flyimport : CompleteInFlyimport ,
449- ) -> Option < LocatedImport > {
450+ ) -> SmallVec < [ LocatedImport ; 1 ] > {
450451 let _p = tracing:: info_span!( "ImportAssets::import_for_item" ) . entered ( ) ;
451452
452- let qualifier = {
453+ let qualifier = ( || {
453454 let mut adjusted_resolved_qualifier = resolved_qualifier;
454455 if !unresolved_qualifier. is_empty ( ) {
455456 match resolved_qualifier {
@@ -464,69 +465,80 @@ fn validate_resolvable(
464465 }
465466
466467 match adjusted_resolved_qualifier {
467- ItemInNs :: Types ( def) => def,
468- _ => return None ,
468+ ItemInNs :: Types ( def) => Some ( def) ,
469+ _ => None ,
469470 }
470- } ;
471- let import_path_candidate = mod_path ( resolved_qualifier) ?;
471+ } ) ( ) ;
472+ let Some ( qualifier) = qualifier else { return SmallVec :: new ( ) } ;
473+ let Some ( import_path_candidate) = mod_path ( resolved_qualifier) else { return SmallVec :: new ( ) } ;
474+ let mut result = SmallVec :: new ( ) ;
472475 let ty = match qualifier {
473476 ModuleDef :: Module ( module) => {
474- return items_locator:: items_with_name_in_module (
477+ items_locator:: items_with_name_in_module :: < Infallible > (
475478 db,
476479 module,
477480 candidate. clone ( ) ,
478481 AssocSearchMode :: Exclude ,
479- |it| match scope_filter ( it) {
480- true => ControlFlow :: Break ( it) ,
481- false => ControlFlow :: Continue ( ( ) ) ,
482+ |item| {
483+ if scope_filter ( item) {
484+ result. push ( LocatedImport :: new (
485+ import_path_candidate. clone ( ) ,
486+ resolved_qualifier,
487+ item,
488+ complete_in_flyimport,
489+ ) ) ;
490+ }
491+ ControlFlow :: Continue ( ( ) )
482492 } ,
483- )
484- . map ( |item| {
485- LocatedImport :: new (
486- import_path_candidate,
487- resolved_qualifier,
488- item,
489- complete_in_flyimport,
490- )
491- } ) ;
493+ ) ;
494+ return result;
492495 }
493496 // FIXME
494- ModuleDef :: Trait ( _) => return None ,
497+ ModuleDef :: Trait ( _) => return SmallVec :: new ( ) ,
495498 ModuleDef :: TypeAlias ( alias) => alias. ty ( db) ,
496499 ModuleDef :: BuiltinType ( builtin) => builtin. ty ( db) ,
497500 ModuleDef :: Adt ( adt) => adt. ty ( db) ,
498- _ => return None ,
501+ _ => return SmallVec :: new ( ) ,
499502 } ;
500- ty. iterate_path_candidates ( db, scope, & FxHashSet :: default ( ) , None , None , |assoc| {
501- // FIXME: Support extra trait imports
502- if assoc. container_or_implemented_trait ( db) . is_some ( ) {
503- return None ;
504- }
505- let name = assoc. name ( db) ?;
506- let is_match = match candidate {
507- NameToImport :: Prefix ( text, true ) => name. as_str ( ) . starts_with ( text) ,
508- NameToImport :: Prefix ( text, false ) => {
509- name. as_str ( ) . chars ( ) . zip ( text. chars ( ) ) . all ( |( name_char, candidate_char) | {
510- name_char. eq_ignore_ascii_case ( & candidate_char)
511- } )
503+ ty. iterate_path_candidates :: < Infallible > (
504+ db,
505+ scope,
506+ & FxHashSet :: default ( ) ,
507+ None ,
508+ None ,
509+ |assoc| {
510+ // FIXME: Support extra trait imports
511+ if assoc. container_or_implemented_trait ( db) . is_some ( ) {
512+ return None ;
512513 }
513- NameToImport :: Exact ( text, true ) => name. as_str ( ) == text,
514- NameToImport :: Exact ( text, false ) => name. as_str ( ) . eq_ignore_ascii_case ( text) ,
515- NameToImport :: Fuzzy ( text, true ) => text. chars ( ) . all ( |c| name. as_str ( ) . contains ( c) ) ,
516- NameToImport :: Fuzzy ( text, false ) => text
517- . chars ( )
518- . all ( |c| name. as_str ( ) . chars ( ) . any ( |name_char| name_char. eq_ignore_ascii_case ( & c) ) ) ,
519- } ;
520- if !is_match {
521- return None ;
522- }
523- Some ( LocatedImport :: new (
524- import_path_candidate. clone ( ) ,
525- resolved_qualifier,
526- assoc_to_item ( assoc) ,
527- complete_in_flyimport,
528- ) )
529- } )
514+ let name = assoc. name ( db) ?;
515+ let is_match = match candidate {
516+ NameToImport :: Prefix ( text, true ) => name. as_str ( ) . starts_with ( text) ,
517+ NameToImport :: Prefix ( text, false ) => {
518+ name. as_str ( ) . chars ( ) . zip ( text. chars ( ) ) . all ( |( name_char, candidate_char) | {
519+ name_char. eq_ignore_ascii_case ( & candidate_char)
520+ } )
521+ }
522+ NameToImport :: Exact ( text, true ) => name. as_str ( ) == text,
523+ NameToImport :: Exact ( text, false ) => name. as_str ( ) . eq_ignore_ascii_case ( text) ,
524+ NameToImport :: Fuzzy ( text, true ) => text. chars ( ) . all ( |c| name. as_str ( ) . contains ( c) ) ,
525+ NameToImport :: Fuzzy ( text, false ) => text. chars ( ) . all ( |c| {
526+ name. as_str ( ) . chars ( ) . any ( |name_char| name_char. eq_ignore_ascii_case ( & c) )
527+ } ) ,
528+ } ;
529+ if !is_match {
530+ return None ;
531+ }
532+ result. push ( LocatedImport :: new (
533+ import_path_candidate. clone ( ) ,
534+ resolved_qualifier,
535+ assoc_to_item ( assoc) ,
536+ complete_in_flyimport,
537+ ) ) ;
538+ None
539+ } ,
540+ ) ;
541+ result
530542}
531543
532544pub fn item_for_path_search ( db : & RootDatabase , item : ItemInNs ) -> Option < ItemInNs > {
0 commit comments