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.rs33
1 files changed, 30 insertions, 3 deletions
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs
index a71d8e9002..c597555a3b 100644
--- a/crates/ide-db/src/imports/import_assets.rs
+++ b/crates/ide-db/src/imports/import_assets.rs
@@ -1,8 +1,9 @@
//! Look up accessible paths for items.
use hir::{
- AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, ModPath, Module, ModuleDef, Name,
- PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type,
+ db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ItemInNs,
+ ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
+ SemanticsScope, Trait, Type,
};
use itertools::{EitherOrBoth, Itertools};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -517,7 +518,7 @@ fn trait_applicable_items(
let related_traits = inherent_traits.chain(env_traits).collect::<FxHashSet<_>>();
let mut required_assoc_items = FxHashSet::default();
- let trait_candidates: FxHashSet<_> = items_locator::items_with_name(
+ let mut trait_candidates: FxHashSet<_> = items_locator::items_with_name(
sema,
current_crate,
trait_candidate.assoc_item_name.clone(),
@@ -538,6 +539,32 @@ fn trait_applicable_items(
})
.collect();
+ trait_candidates.retain(|&candidate_trait_id| {
+ // we care about the following cases:
+ // 1. Trait's definition crate
+ // 2. Definition crates for all trait's generic arguments
+ // a. This is recursive for fundamental types: `Into<Box<A>> for ()`` is OK, but
+ // `Into<Vec<A>> for ()`` is *not*.
+ // 3. Receiver type definition crate
+ // a. This is recursive for fundamental types
+ let defining_crate_for_trait = Trait::from(candidate_trait_id).krate(db);
+ let Some(receiver) = trait_candidate.receiver_ty.fingerprint_for_trait_impl() else {
+ return false;
+ };
+ let definitions_exist_in_trait_crate = db
+ .trait_impls_in_crate(defining_crate_for_trait.into())
+ .has_impls_for_trait_and_self_ty(candidate_trait_id, receiver);
+
+ // 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 = || {
+ db.trait_impls_in_crate(trait_candidate.receiver_ty.krate(db).into())
+ .has_impls_for_trait_and_self_ty(candidate_trait_id, receiver)
+ };
+
+ definitions_exist_in_trait_crate || definitions_exist_in_receiver_crate()
+ });
+
let mut located_imports = FxHashSet::default();
let mut trait_import_paths = FxHashMap::default();