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.rs77
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) {