Skip to content

Commit 6241567

Browse files
committed
Speedup trait impl search for goto_implementation
1 parent 6c782a5 commit 6241567

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

crates/hir/src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
5151
use hir_ty::{
5252
autoderef,
5353
display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
54-
method_resolution, to_assoc_type_id,
54+
method_resolution::{self, TyFingerprint},
55+
to_assoc_type_id,
5556
traits::{FnTrait, Solution, SolutionVariables},
5657
AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
5758
InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
@@ -1500,13 +1501,20 @@ impl Impl {
15001501
def_crates.iter().for_each(|&id| {
15011502
all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
15021503
});
1504+
let fp = TyFingerprint::for_impl(&ty.value);
15031505
for id in def_crates
15041506
.iter()
15051507
.flat_map(|&id| Crate { id }.reverse_dependencies(db))
15061508
.map(|Crate { id }| id)
15071509
.chain(def_crates.iter().copied())
15081510
{
1509-
all.extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter));
1511+
match fp {
1512+
Some(fp) => all.extend(
1513+
db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
1514+
),
1515+
None => all
1516+
.extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)),
1517+
}
15101518
}
15111519
all
15121520
}

crates/hir_ty/src/method_resolution.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl TyFingerprint {
4444
/// Creates a TyFingerprint for looking up an impl. Only certain types can
4545
/// have impls: if we have some `struct S`, we can have an `impl S`, but not
4646
/// `impl &S`. Hence, this will return `None` for reference types and such.
47-
pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
47+
pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
4848
let fp = match *ty.interned(&Interner) {
4949
TyKind::Str => TyFingerprint::Str,
5050
TyKind::Never => TyFingerprint::Never,
@@ -141,6 +141,14 @@ impl TraitImpls {
141141
}
142142
}
143143

144+
/// Queries all trait impls for the given type.
145+
pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ {
146+
self.map
147+
.values()
148+
.flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp))))
149+
.flat_map(|it| it.iter().copied())
150+
}
151+
144152
/// Queries all impls of the given trait.
145153
pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
146154
self.map

0 commit comments

Comments
 (0)