Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/imports/import_assets.rs')
| -rw-r--r-- | crates/ide-db/src/imports/import_assets.rs | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index 0c235c8d9a..c49ade2350 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -1,14 +1,15 @@ //! Look up accessible paths for items. -use std::ops::ControlFlow; +use std::{convert::Infallible, ops::ControlFlow}; use hir::{ AsAssocItem, AssocItem, AssocItemContainer, Complete, Crate, FindPathConfig, HasCrate, ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, - SemanticsScope, Trait, TyFingerprint, Type, db::HirDatabase, + SemanticsScope, Trait, Type, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; +use smallvec::SmallVec; use syntax::{ AstNode, SyntaxNode, ast::{self, HasName, make}, @@ -416,7 +417,7 @@ fn path_applicable_imports( NameToImport::Exact(first_qsegment.as_str().to_owned(), true), AssocSearchMode::Exclude, ) - .filter_map(|(item, do_not_complete)| { + .flat_map(|(item, do_not_complete)| { // we found imports for `first_qsegment`, now we need to filter these imports by whether // they result in resolving the rest of the path successfully validate_resolvable( @@ -446,10 +447,10 @@ fn validate_resolvable( resolved_qualifier: ItemInNs, unresolved_qualifier: &[Name], complete_in_flyimport: CompleteInFlyimport, -) -> Option<LocatedImport> { +) -> SmallVec<[LocatedImport; 1]> { let _p = tracing::info_span!("ImportAssets::import_for_item").entered(); - let qualifier = { + let qualifier = (|| { let mut adjusted_resolved_qualifier = resolved_qualifier; if !unresolved_qualifier.is_empty() { match resolved_qualifier { @@ -464,40 +465,42 @@ fn validate_resolvable( } match adjusted_resolved_qualifier { - ItemInNs::Types(def) => def, - _ => return None, + ItemInNs::Types(def) => Some(def), + _ => None, } - }; - let import_path_candidate = mod_path(resolved_qualifier)?; + })(); + let Some(qualifier) = qualifier else { return SmallVec::new() }; + let Some(import_path_candidate) = mod_path(resolved_qualifier) else { return SmallVec::new() }; + let mut result = SmallVec::new(); let ty = match qualifier { ModuleDef::Module(module) => { - return items_locator::items_with_name_in_module( + items_locator::items_with_name_in_module::<Infallible>( db, module, candidate.clone(), AssocSearchMode::Exclude, - |it| match scope_filter(it) { - true => ControlFlow::Break(it), - false => ControlFlow::Continue(()), + |item| { + if scope_filter(item) { + result.push(LocatedImport::new( + import_path_candidate.clone(), + resolved_qualifier, + item, + complete_in_flyimport, + )); + } + ControlFlow::Continue(()) }, - ) - .map(|item| { - LocatedImport::new( - import_path_candidate, - resolved_qualifier, - item, - complete_in_flyimport, - ) - }); + ); + return result; } // FIXME - ModuleDef::Trait(_) => return None, + ModuleDef::Trait(_) => return SmallVec::new(), ModuleDef::TypeAlias(alias) => alias.ty(db), ModuleDef::BuiltinType(builtin) => builtin.ty(db), ModuleDef::Adt(adt) => adt.ty(db), - _ => return None, + _ => return SmallVec::new(), }; - ty.iterate_path_candidates(db, scope, &FxHashSet::default(), None, None, |assoc| { + ty.iterate_path_candidates::<Infallible>(db, scope, &FxHashSet::default(), None, |assoc| { // FIXME: Support extra trait imports if assoc.container_or_implemented_trait(db).is_some() { return None; @@ -520,13 +523,15 @@ fn validate_resolvable( if !is_match { return None; } - Some(LocatedImport::new( + result.push(LocatedImport::new( import_path_candidate.clone(), resolved_qualifier, assoc_to_item(assoc), complete_in_flyimport, - )) - }) + )); + None + }); + result } pub fn item_for_path_search(db: &RootDatabase, item: ItemInNs) -> Option<ItemInNs> { @@ -596,7 +601,6 @@ fn trait_applicable_items<'db>( deref_chain .into_iter() .filter_map(|ty| Some((ty.krate(db).into(), ty.fingerprint_for_trait_impl()?))) - .sorted() .unique() .collect::<Vec<_>>() }; @@ -607,11 +611,11 @@ fn trait_applicable_items<'db>( } // in order to handle implied bounds through an associated type, keep all traits if any - // type in the deref chain matches `TyFingerprint::Unnameable`. This fingerprint + // type in the deref chain matches `SimplifiedType::Placeholder`. This fingerprint // won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual implementations. if !autoderef_method_receiver .iter() - .any(|(_, fingerprint)| matches!(fingerprint, TyFingerprint::Unnameable)) + .any(|(_, fingerprint)| matches!(fingerprint, hir::SimplifiedType::Placeholder)) { trait_candidates.retain(|&candidate_trait_id| { // we care about the following cases: @@ -623,17 +627,18 @@ fn trait_applicable_items<'db>( // a. This is recursive for fundamental types let defining_crate_for_trait = Trait::from(candidate_trait_id).krate(db); - let trait_impls_in_crate = db.trait_impls_in_crate(defining_crate_for_trait.into()); + let trait_impls_in_crate = + hir::TraitImpls::for_crate(db, defining_crate_for_trait.into()); let definitions_exist_in_trait_crate = - autoderef_method_receiver.iter().any(|&(_, fingerprint)| { + autoderef_method_receiver.iter().any(|(_, fingerprint)| { trait_impls_in_crate .has_impls_for_trait_and_self_ty(candidate_trait_id, fingerprint) }); // this is a closure for laziness: if `definitions_exist_in_trait_crate` is true, // we can avoid a second db lookup. let definitions_exist_in_receiver_crate = || { - autoderef_method_receiver.iter().any(|&(krate, fingerprint)| { - db.trait_impls_in_crate(krate) + autoderef_method_receiver.iter().any(|(krate, fingerprint)| { + hir::TraitImpls::for_crate(db, *krate) .has_impls_for_trait_and_self_ty(candidate_trait_id, fingerprint) }) }; @@ -651,7 +656,6 @@ fn trait_applicable_items<'db>( scope, &trait_candidates, None, - None, |assoc| { if let Some(&complete_in_flyimport) = required_assoc_items.get(&assoc) { let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?; @@ -676,7 +680,6 @@ fn trait_applicable_items<'db>( scope, &trait_candidates, None, - None, |function| { let assoc = function.as_assoc_item(db)?; if let Some(&complete_in_flyimport) = required_assoc_items.get(&assoc) { |