Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
| -rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 100 |
1 files changed, 45 insertions, 55 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 768772d5c3..d5285c1710 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -8,9 +8,8 @@ use arrayvec::ArrayVec; use base_db::{CrateId, Edition}; use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; use hir_def::{ - item_scope::ItemScope, lang_item::LangItemTarget, nameres::DefMap, AssocItemId, BlockId, - ConstId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, - ModuleId, TraitId, + item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId, FunctionId, + GenericDefId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId, }; use hir_expand::name::Name; use rustc_hash::{FxHashMap, FxHashSet}; @@ -21,7 +20,7 @@ use crate::{ db::HirDatabase, from_foreign_def_id, infer::{unify::InferenceTable, Adjust, Adjustment, AutoBorrow, OverloadedDeref, PointerCast}, - primitive::{self, FloatTy, IntTy, UintTy}, + primitive::{FloatTy, IntTy, UintTy}, static_lifetime, utils::all_super_traits, AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner, @@ -337,6 +336,30 @@ impl InherentImpls { } } +pub fn inherent_impl_crates_query( + db: &dyn HirDatabase, + krate: CrateId, + fp: TyFingerprint, +) -> ArrayVec<CrateId, 2> { + let _p = profile::span("inherent_impl_crates_query"); + let mut res = ArrayVec::new(); + let crate_graph = db.crate_graph(); + + for krate in crate_graph.transitive_deps(krate) { + if res.is_full() { + // we don't currently look for or store more than two crates here, + // so don't needlessly look at more crates than necessary. + break; + } + let impls = db.inherent_impls_in_crate(krate); + if impls.map.get(&fp).map_or(false, |v| !v.is_empty()) { + res.push(krate); + } + } + + res +} + fn collect_unnamed_consts<'a>( db: &'a dyn HirDatabase, scope: &'a ItemScope, @@ -370,63 +393,30 @@ pub fn def_crates( ty: &Ty, cur_crate: CrateId, ) -> Option<ArrayVec<CrateId, 2>> { - // Types like slice can have inherent impls in several crates, (core and alloc). - // The corresponding impls are marked with lang items, so we can use them to find the required crates. - macro_rules! lang_item_crate { - ($($name:expr),+ $(,)?) => {{ - let mut v = ArrayVec::<LangItemTarget, 2>::new(); - $( - v.extend(db.lang_item(cur_crate, $name.into())); - )+ - v - }}; - } - let mod_to_crate_ids = |module: ModuleId| Some(iter::once(module.krate()).collect()); - let lang_item_targets = match ty.kind(Interner) { - TyKind::Adt(AdtId(def_id), _) => { - return mod_to_crate_ids(def_id.module(db.upcast())); - } + let fp = TyFingerprint::for_inherent_impl(ty); + + match ty.kind(Interner) { + TyKind::Adt(AdtId(def_id), _) => mod_to_crate_ids(def_id.module(db.upcast())), TyKind::Foreign(id) => { - return mod_to_crate_ids( - from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()), - ); - } - TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"), - TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"), - TyKind::Scalar(Scalar::Float(f)) => match f { - // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) - FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), - FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), - }, - &TyKind::Scalar(Scalar::Int(t)) => { - lang_item_crate!(primitive::int_ty_to_string(t)) + mod_to_crate_ids(from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast())) } - &TyKind::Scalar(Scalar::Uint(t)) => { - lang_item_crate!(primitive::uint_ty_to_string(t)) - } - TyKind::Str => lang_item_crate!("str_alloc", "str"), - TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"), - TyKind::Array(..) => lang_item_crate!("array"), - TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), - TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), - TyKind::Dyn(_) => { - return ty.dyn_trait().and_then(|trait_| { - mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) - }); + TyKind::Dyn(_) => ty + .dyn_trait() + .and_then(|trait_| mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))), + // for primitives, there may be impls in various places (core and alloc + // mostly). We just check the whole crate graph for crates with impls + // (cached behind a query). + TyKind::Scalar(_) + | TyKind::Str + | TyKind::Slice(_) + | TyKind::Array(..) + | TyKind::Raw(..) => { + Some(db.inherent_impl_crates(cur_crate, fp.expect("fingerprint for primitive"))) } _ => return None, - }; - let res = lang_item_targets - .into_iter() - .filter_map(|it| match it { - LangItemTarget::ImplDefId(it) => Some(it), - _ => None, - }) - .map(|it| it.lookup(db.upcast()).container.krate()) - .collect(); - Some(res) + } } /// Look up the method with the given name. |