]> git.lizzy.rs Git - rust.git/commitdiff
Speedup trait impl search for goto_implementation
authorLukas Wirth <lukastw97@gmail.com>
Mon, 15 Mar 2021 12:49:21 +0000 (13:49 +0100)
committerLukas Wirth <lukastw97@gmail.com>
Mon, 15 Mar 2021 12:49:21 +0000 (13:49 +0100)
crates/hir/src/lib.rs
crates/hir_ty/src/method_resolution.rs

index a9d3c915665fea84273d7a1994e705189d39fc67..42a805c57503fa4661a32a0723de03c918119071 100644 (file)
@@ -51,7 +51,8 @@
 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 @@ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec<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
     }
index c7055bee50f53ded867af64ffdf020f195f44107..57f37ef4b3e9e5fc7301570fdf8fcf22760569ce 100644 (file)
@@ -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<TyFingerprint> {
+    pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
         let fp = match *ty.interned(&Interner) {
             TyKind::Str => TyFingerprint::Str,
             TyKind::Never => TyFingerprint::Never,
@@ -141,6 +141,14 @@ fn merge(&mut self, other: &Self) {
         }
     }
 
+    /// Queries all trait impls for the given type.
+    pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ {
+        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<Item = ImplId> + '_ {
         self.map