diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-20 23:14:21 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-20 23:14:21 +0100 |
commit | 04d64267de2c9ade61ae9fdbc98114599c11a2d7 (patch) | |
tree | eb18414e177eb0e40e902c5ec45cebc49ac8d43b /crates/ra_hir_ty/src/traits.rs | |
parent | 92fef01f6506b33c0489e020df1ad9fdce2fac9b (diff) | |
parent | a3c2f5126fb9f2575584d12335b6e7e82deec45a (diff) |
Merge #4947
4947: Replace `impls_in_trait` query with smarter use of `CrateImplDefs` r=matklad a=jonas-schievink
`impls_in_trait` was allocating a whopping ~400 MB of RAM when running analysis-stats on r-a itself.
Remove it, instead adding a query that computes a summary `CrateImplDefs` map for all transitive dependencies. This can probably still be made more efficient, but this already reduces the peak memory usage by 25% without much performance impact on analysis-stats.
**Before**:
```
Total: 34.962107188s, 2083mb allocated 2141mb resident
422mb ImplsForTraitQuery (deps)
250mb CrateDefMapQueryQuery
147mb MacroArgQuery
140mb TraitSolveQuery (deps)
68mb InferQueryQuery (deps)
62mb ImplDatumQuery (deps)
```
**After**:
```
Total: 35.261100358s, 1520mb allocated 1569mb resident
250mb CrateDefMapQueryQuery
147mb MacroArgQuery
144mb TraitSolveQuery (deps)
68mb InferQueryQuery (deps)
61mb ImplDatumQuery (deps)
45mb BodyQuery
45mb ImplDatumQuery
```
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/traits.rs')
-rw-r--r-- | crates/ra_hir_ty/src/traits.rs | 31 |
1 files changed, 1 insertions, 30 deletions
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 892fbd6d1..6f43c3a22 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -7,9 +7,8 @@ use hir_def::{ | |||
7 | }; | 7 | }; |
8 | use ra_db::{impl_intern_key, salsa, CrateId}; | 8 | use ra_db::{impl_intern_key, salsa, CrateId}; |
9 | use ra_prof::profile; | 9 | use ra_prof::profile; |
10 | use rustc_hash::FxHashSet; | ||
11 | 10 | ||
12 | use crate::{db::HirDatabase, method_resolution::TyFingerprint, DebruijnIndex}; | 11 | use crate::{db::HirDatabase, DebruijnIndex}; |
13 | 12 | ||
14 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 13 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
15 | 14 | ||
@@ -38,34 +37,6 @@ fn create_chalk_solver() -> chalk_solve::Solver<Interner> { | |||
38 | solver_choice.into_solver() | 37 | solver_choice.into_solver() |
39 | } | 38 | } |
40 | 39 | ||
41 | /// Collects impls for the given trait in the whole dependency tree of `krate`. | ||
42 | pub(crate) fn impls_for_trait_query( | ||
43 | db: &dyn HirDatabase, | ||
44 | krate: CrateId, | ||
45 | trait_: TraitId, | ||
46 | self_ty_fp: Option<TyFingerprint>, | ||
47 | ) -> Arc<[ImplId]> { | ||
48 | // FIXME: We could be a lot smarter here - because of the orphan rules and | ||
49 | // the fact that the trait and the self type need to be in the dependency | ||
50 | // tree of a crate somewhere for an impl to exist, we could skip looking in | ||
51 | // a lot of crates completely | ||
52 | let mut impls = FxHashSet::default(); | ||
53 | // We call the query recursively here. On the one hand, this means we can | ||
54 | // reuse results from queries for different crates; on the other hand, this | ||
55 | // will only ever get called for a few crates near the root of the tree (the | ||
56 | // ones the user is editing), so this may actually be a waste of memory. I'm | ||
57 | // doing it like this mainly for simplicity for now. | ||
58 | for dep in &db.crate_graph()[krate].dependencies { | ||
59 | impls.extend(db.impls_for_trait(dep.crate_id, trait_, self_ty_fp).iter()); | ||
60 | } | ||
61 | let crate_impl_defs = db.impls_in_crate(krate); | ||
62 | match self_ty_fp { | ||
63 | Some(fp) => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp)), | ||
64 | None => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)), | ||
65 | } | ||
66 | impls.into_iter().collect() | ||
67 | } | ||
68 | |||
69 | /// A set of clauses that we assume to be true. E.g. if we are inside this function: | 40 | /// A set of clauses that we assume to be true. E.g. if we are inside this function: |
70 | /// ```rust | 41 | /// ```rust |
71 | /// fn foo<T: Default>(t: T) {} | 42 | /// fn foo<T: Default>(t: T) {} |