Improve indexing of impls
Store impls for e.g. &Foo with the ones for Foo instead of the big "other" bucket. This can improve performance and simplifies the HIR impl search a bit.
This commit is contained in:
parent
354151df35
commit
fdd721e9ef
@ -1580,11 +1580,24 @@ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<I
|
|||||||
ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
|
ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fp = TyFingerprint::for_inherent_impl(&ty);
|
||||||
|
let fp = if let Some(fp) = fp {
|
||||||
|
fp
|
||||||
|
} else {
|
||||||
|
return Vec::new();
|
||||||
|
};
|
||||||
|
|
||||||
let mut all = Vec::new();
|
let mut all = Vec::new();
|
||||||
def_crates.iter().for_each(|&id| {
|
def_crates.iter().for_each(|&id| {
|
||||||
all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
|
all.extend(
|
||||||
|
db.inherent_impls_in_crate(id)
|
||||||
|
.for_self_ty(&ty)
|
||||||
|
.into_iter()
|
||||||
|
.cloned()
|
||||||
|
.map(Self::from)
|
||||||
|
.filter(filter),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
let fp = TyFingerprint::for_impl(&ty);
|
|
||||||
for id in def_crates
|
for id in def_crates
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
|
.flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
|
||||||
@ -1592,13 +1605,12 @@ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<I
|
|||||||
.chain(def_crates.iter().copied())
|
.chain(def_crates.iter().copied())
|
||||||
.unique()
|
.unique()
|
||||||
{
|
{
|
||||||
match fp {
|
all.extend(
|
||||||
Some(fp) => all.extend(
|
db.trait_impls_in_crate(id)
|
||||||
db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
|
.for_self_ty_without_blanket_impls(fp)
|
||||||
),
|
.map(Self::from)
|
||||||
None => all
|
.filter(filter),
|
||||||
.extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)),
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
all
|
all
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
use stdx::always;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
autoderef,
|
autoderef,
|
||||||
@ -21,32 +22,36 @@
|
|||||||
primitive::{self, FloatTy, IntTy, UintTy},
|
primitive::{self, FloatTy, IntTy, UintTy},
|
||||||
static_lifetime,
|
static_lifetime,
|
||||||
utils::all_super_traits,
|
utils::all_super_traits,
|
||||||
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
|
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner,
|
||||||
InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder,
|
Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
|
||||||
TyExt, TyKind,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is used as a key for indexing impls.
|
/// This is used as a key for indexing impls.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum TyFingerprint {
|
pub enum TyFingerprint {
|
||||||
|
// These are lang item impls:
|
||||||
Str,
|
Str,
|
||||||
Slice,
|
Slice,
|
||||||
Array,
|
Array,
|
||||||
Never,
|
Never,
|
||||||
RawPtr(Mutability),
|
RawPtr(Mutability),
|
||||||
Scalar(Scalar),
|
Scalar(Scalar),
|
||||||
|
// These can have user-defined impls:
|
||||||
Adt(hir_def::AdtId),
|
Adt(hir_def::AdtId),
|
||||||
Dyn(TraitId),
|
Dyn(TraitId),
|
||||||
Tuple(usize),
|
|
||||||
ForeignType(ForeignDefId),
|
ForeignType(ForeignDefId),
|
||||||
FnPtr(usize, FnSig),
|
// These only exist for trait impls
|
||||||
|
Unit,
|
||||||
|
Unnameable,
|
||||||
|
Function(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyFingerprint {
|
impl TyFingerprint {
|
||||||
/// Creates a TyFingerprint for looking up an impl. Only certain types can
|
/// Creates a TyFingerprint for looking up an inherent impl. Only certain
|
||||||
/// have impls: if we have some `struct S`, we can have an `impl S`, but not
|
/// types can have inherent impls: if we have some `struct S`, we can have
|
||||||
/// `impl &S`. Hence, this will return `None` for reference types and such.
|
/// an `impl S`, but not `impl &S`. Hence, this will return `None` for
|
||||||
pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
|
/// reference types and such.
|
||||||
|
pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
|
||||||
let fp = match ty.kind(&Interner) {
|
let fp = match ty.kind(&Interner) {
|
||||||
TyKind::Str => TyFingerprint::Str,
|
TyKind::Str => TyFingerprint::Str,
|
||||||
TyKind::Never => TyFingerprint::Never,
|
TyKind::Never => TyFingerprint::Never,
|
||||||
@ -54,17 +59,52 @@ pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
|
|||||||
TyKind::Array(..) => TyFingerprint::Array,
|
TyKind::Array(..) => TyFingerprint::Array,
|
||||||
TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
|
TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
|
||||||
TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
|
TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
|
||||||
TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(*cardinality),
|
|
||||||
TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
|
TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
|
||||||
TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
|
TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
|
||||||
TyKind::Function(FnPointer { sig, substitution: substs, .. }) => {
|
|
||||||
TyFingerprint::FnPtr(substs.0.len(&Interner) - 1, *sig)
|
|
||||||
}
|
|
||||||
TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
|
TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(fp)
|
Some(fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a TyFingerprint for looking up a trait impl.
|
||||||
|
pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
|
||||||
|
let fp = match ty.kind(&Interner) {
|
||||||
|
TyKind::Str => TyFingerprint::Str,
|
||||||
|
TyKind::Never => TyFingerprint::Never,
|
||||||
|
TyKind::Slice(..) => TyFingerprint::Slice,
|
||||||
|
TyKind::Array(..) => TyFingerprint::Array,
|
||||||
|
TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
|
||||||
|
TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
|
||||||
|
TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
|
||||||
|
TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
|
||||||
|
TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
|
||||||
|
TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
|
||||||
|
TyKind::Tuple(_, subst) => {
|
||||||
|
let first_ty = subst.interned().get(0).map(|arg| arg.assert_ty_ref(&Interner));
|
||||||
|
if let Some(ty) = first_ty {
|
||||||
|
return TyFingerprint::for_trait_impl(ty);
|
||||||
|
} else {
|
||||||
|
TyFingerprint::Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TyKind::AssociatedType(_, _)
|
||||||
|
| TyKind::OpaqueType(_, _)
|
||||||
|
| TyKind::FnDef(_, _)
|
||||||
|
| TyKind::Closure(_, _)
|
||||||
|
| TyKind::Generator(..)
|
||||||
|
| TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable,
|
||||||
|
TyKind::Function(fn_ptr) => {
|
||||||
|
TyFingerprint::Function(fn_ptr.substitution.0.len(&Interner) as u32)
|
||||||
|
}
|
||||||
|
TyKind::Alias(_)
|
||||||
|
| TyKind::Placeholder(_)
|
||||||
|
| TyKind::BoundVar(_)
|
||||||
|
| TyKind::InferenceVar(_, _)
|
||||||
|
| TyKind::Error => return None,
|
||||||
|
};
|
||||||
|
Some(fp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
|
pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
|
||||||
@ -112,7 +152,7 @@ fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpl
|
|||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
let self_ty = db.impl_self_ty(impl_id);
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders());
|
let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
|
||||||
impls
|
impls
|
||||||
.map
|
.map
|
||||||
.entry(target_trait)
|
.entry(target_trait)
|
||||||
@ -157,10 +197,13 @@ fn merge(&mut self, other: &Self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Queries all trait impls for the given type.
|
/// Queries all trait impls for the given type.
|
||||||
pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ {
|
pub fn for_self_ty_without_blanket_impls(
|
||||||
|
&self,
|
||||||
|
fp: TyFingerprint,
|
||||||
|
) -> impl Iterator<Item = ImplId> + '_ {
|
||||||
self.map
|
self.map
|
||||||
.values()
|
.values()
|
||||||
.flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp))))
|
.flat_map(move |impls| impls.get(&Some(fp)).into_iter())
|
||||||
.flat_map(|it| it.iter().copied())
|
.flat_map(|it| it.iter().copied())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +258,9 @@ pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId
|
|||||||
}
|
}
|
||||||
|
|
||||||
let self_ty = db.impl_self_ty(impl_id);
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
if let Some(fp) = TyFingerprint::for_impl(self_ty.skip_binders()) {
|
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
|
||||||
|
always!(fp.is_some());
|
||||||
|
if let Some(fp) = fp {
|
||||||
map.entry(fp).or_default().push(impl_id);
|
map.entry(fp).or_default().push(impl_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,7 +273,7 @@ pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
|
pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
|
||||||
match TyFingerprint::for_impl(self_ty) {
|
match TyFingerprint::for_inherent_impl(self_ty) {
|
||||||
Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
|
Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
|
||||||
None => &[],
|
None => &[],
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ fn binder_kind(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
let self_ty_fp = TyFingerprint::for_impl(&ty);
|
let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
|
||||||
let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
|
let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
|
||||||
Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
|
Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
|
||||||
Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
|
Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
|
||||||
|
Loading…
Reference in New Issue
Block a user