aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-03-15 12:49:21 +0000
committerLukas Wirth <[email protected]>2021-03-15 12:49:21 +0000
commit6241567948b644739d2ae904e74f5f10cd5b2bb6 (patch)
tree7af5ca0990c536409ea1e2044f0fc5aa63a3702d
parent6c782a53148dc2f34be2eafbdf872ab6497632fd (diff)
Speedup trait impl search for goto_implementation
-rw-r--r--crates/hir/src/lib.rs12
-rw-r--r--crates/hir_ty/src/method_resolution.rs10
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};
51use hir_ty::{ 51use hir_ty::{
52 autoderef, 52 autoderef,
53 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, 53 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,
55 traits::{FnTrait, Solution, SolutionVariables}, 56 traits::{FnTrait, Solution, SolutionVariables},
56 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, 57 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
57 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty, 58 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
@@ -1500,13 +1501,20 @@ impl Impl {
1500 def_crates.iter().for_each(|&id| { 1501 def_crates.iter().for_each(|&id| {
1501 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) 1502 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
1502 }); 1503 });
1504 let fp = TyFingerprint::for_impl(&ty.value);
1503 for id in def_crates 1505 for id in def_crates
1504 .iter() 1506 .iter()
1505 .flat_map(|&id| Crate { id }.reverse_dependencies(db)) 1507 .flat_map(|&id| Crate { id }.reverse_dependencies(db))
1506 .map(|Crate { id }| id) 1508 .map(|Crate { id }| id)
1507 .chain(def_crates.iter().copied()) 1509 .chain(def_crates.iter().copied())
1508 { 1510 {
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 }
1510 } 1518 }
1511 all 1519 all
1512 } 1520 }
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 {
44 /// Creates a TyFingerprint for looking up an impl. Only certain types can 44 /// Creates a TyFingerprint for looking up an impl. Only certain types can
45 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 45 /// have impls: if we have some `struct S`, we can have an `impl S`, but not
46 /// `impl &S`. Hence, this will return `None` for reference types and such. 46 /// `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> {
48 let fp = match *ty.interned(&Interner) { 48 let fp = match *ty.interned(&Interner) {
49 TyKind::Str => TyFingerprint::Str, 49 TyKind::Str => TyFingerprint::Str,
50 TyKind::Never => TyFingerprint::Never, 50 TyKind::Never => TyFingerprint::Never,
@@ -141,6 +141,14 @@ impl TraitImpls {
141 } 141 }
142 } 142 }
143 143
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
144 /// Queries all impls of the given trait. 152 /// Queries all impls of the given trait.
145 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ { 153 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
146 self.map 154 self.map