From 6241567948b644739d2ae904e74f5f10cd5b2bb6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Mar 2021 13:49:21 +0100 Subject: Speedup trait impl search for goto_implementation --- crates/hir/src/lib.rs | 12 ++++++++++-- crates/hir_ty/src/method_resolution.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a9d3c9156..42a805c57 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -51,7 +51,8 @@ use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; use hir_ty::{ autoderef, display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, - method_resolution, to_assoc_type_id, + method_resolution::{self, TyFingerprint}, + to_assoc_type_id, traits::{FnTrait, Solution, SolutionVariables}, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty, @@ -1500,13 +1501,20 @@ impl Impl { def_crates.iter().for_each(|&id| { all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) }); + let fp = TyFingerprint::for_impl(&ty.value); for id in def_crates .iter() .flat_map(|&id| Crate { id }.reverse_dependencies(db)) .map(|Crate { id }| id) .chain(def_crates.iter().copied()) { - all.extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)); + match fp { + Some(fp) => all.extend( + db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), + ), + None => all + .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)), + } } all } diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index c7055bee5..57f37ef4b 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -44,7 +44,7 @@ impl TyFingerprint { /// Creates a TyFingerprint for looking up an impl. Only certain types can /// have impls: if we have some `struct S`, we can have an `impl S`, but not /// `impl &S`. Hence, this will return `None` for reference types and such. - pub(crate) fn for_impl(ty: &Ty) -> Option { + pub fn for_impl(ty: &Ty) -> Option { let fp = match *ty.interned(&Interner) { TyKind::Str => TyFingerprint::Str, TyKind::Never => TyFingerprint::Never, @@ -141,6 +141,14 @@ impl TraitImpls { } } + /// Queries all trait impls for the given type. + pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator + '_ { + self.map + .values() + .flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp)))) + .flat_map(|it| it.iter().copied()) + } + /// Queries all impls of the given trait. pub fn for_trait(&self, trait_: TraitId) -> impl Iterator + '_ { self.map -- cgit v1.2.3