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 | 33 |
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(); |