Skip to content

Commit ebd8233

Browse files
Replace impls_in_trait with CrateImplDefs
1 parent 902a9c6 commit ebd8233

File tree

7 files changed

+79
-63
lines changed

7 files changed

+79
-63
lines changed

crates/ra_hir/src/db.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ pub use hir_expand::db::{
1616
pub use hir_ty::db::{
1717
AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery,
1818
GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase,
19-
HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery,
20-
ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery,
21-
InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
22-
TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery,
19+
HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsInCrateQuery,
20+
InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, InternTypeCtorQuery,
21+
InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, TraitDatumQuery,
22+
TraitSolveQuery, TyQuery, ValueTyQuery,
2323
};
2424

2525
#[test]

crates/ra_hir_def/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pub struct TypeAliasId(salsa::InternId);
159159
type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>;
160160
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
161161

162-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
162+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
163163
pub struct ImplId(salsa::InternId);
164164
type ImplLoc = ItemLoc<ast::ImplDef>;
165165
impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);

crates/ra_hir_ty/src/db.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
use std::sync::Arc;
44

55
use hir_def::{
6-
db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId,
7-
TypeParamId, VariantId,
6+
db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TypeParamId,
7+
VariantId,
88
};
99
use ra_arena::map::ArenaMap;
1010
use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
1111
use ra_prof::profile;
1212

1313
use crate::{
14-
method_resolution::{CrateImplDefs, TyFingerprint},
14+
method_resolution::CrateImplDefs,
1515
traits::{chalk, AssocTyValue, Impl},
1616
Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
1717
ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
@@ -70,13 +70,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
7070
#[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
7171
fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
7272

73-
#[salsa::invoke(crate::traits::impls_for_trait_query)]
74-
fn impls_for_trait(
75-
&self,
76-
krate: CrateId,
77-
trait_: TraitId,
78-
self_ty_fp: Option<TyFingerprint>,
79-
) -> Arc<[ImplId]>;
73+
#[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)]
74+
fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>;
8075

8176
// Interned IDs for Chalk integration
8277
#[salsa::interned]

crates/ra_hir_ty/src/method_resolution.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,66 @@ impl TyFingerprint {
3838
}
3939
}
4040

41+
/// A queryable and mergeable collection of impls.
4142
#[derive(Debug, PartialEq, Eq)]
4243
pub struct CrateImplDefs {
43-
impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
44+
inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
4445
impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
4546
}
4647

4748
impl CrateImplDefs {
4849
pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
4950
let _p = profile("impls_in_crate_query");
50-
let mut res =
51-
CrateImplDefs { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() };
51+
let mut res = CrateImplDefs {
52+
inherent_impls: FxHashMap::default(),
53+
impls_by_trait: FxHashMap::default(),
54+
};
55+
res.fill(db, krate);
56+
57+
Arc::new(res)
58+
}
59+
60+
/// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
61+
///
62+
/// The full set of impls that can be used by `krate` is the returned map plus all the impls
63+
/// from `krate` itself.
64+
pub(crate) fn impls_from_deps_query(
65+
db: &dyn HirDatabase,
66+
krate: CrateId,
67+
) -> Arc<CrateImplDefs> {
68+
// FIXME: This should take visibility and orphan rules into account to keep the result
69+
// smaller.
70+
let _p = profile("impls_from_deps_query");
71+
let crate_graph = db.crate_graph();
72+
let mut res = CrateImplDefs {
73+
inherent_impls: FxHashMap::default(),
74+
impls_by_trait: FxHashMap::default(),
75+
};
76+
let mut seen = FxHashSet::default();
77+
let mut worklist = vec![krate];
78+
while let Some(krate) = worklist.pop() {
79+
if !seen.insert(krate) {
80+
continue;
81+
}
5282

83+
// No deduplication, since a) impls can't be reexported, b) we visit a crate only once
84+
res.fill(db, krate);
85+
86+
worklist.extend(crate_graph[krate].dependencies.iter().map(|dep| dep.crate_id));
87+
}
88+
89+
Arc::new(res)
90+
}
91+
92+
fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
5393
let crate_def_map = db.crate_def_map(krate);
5494
for (_module_id, module_data) in crate_def_map.modules.iter() {
5595
for impl_id in module_data.scope.impls() {
5696
match db.impl_trait(impl_id) {
5797
Some(tr) => {
5898
let self_ty = db.impl_self_ty(impl_id);
5999
let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
60-
res.impls_by_trait
100+
self.impls_by_trait
61101
.entry(tr.value.trait_)
62102
.or_default()
63103
.entry(self_ty_fp)
@@ -67,18 +107,17 @@ impl CrateImplDefs {
67107
None => {
68108
let self_ty = db.impl_self_ty(impl_id);
69109
if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
70-
res.impls.entry(self_ty_fp).or_default().push(impl_id);
110+
self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
71111
}
72112
}
73113
}
74114
}
75115
}
76-
77-
Arc::new(res)
78116
}
117+
79118
pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
80119
let fingerprint = TyFingerprint::for_impl(ty);
81-
fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
120+
fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
82121
}
83122

84123
pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
@@ -110,7 +149,7 @@ impl CrateImplDefs {
110149
}
111150

112151
pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
113-
self.impls
152+
self.inherent_impls
114153
.values()
115154
.chain(self.impls_by_trait.values().flat_map(|m| m.values()))
116155
.flatten()

crates/ra_hir_ty/src/traits.rs

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ use chalk_ir::cast::Cast;
55
use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
66
use ra_db::{impl_intern_key, salsa, CrateId};
77
use ra_prof::profile;
8-
use rustc_hash::FxHashSet;
98

10-
use crate::{db::HirDatabase, method_resolution::TyFingerprint, DebruijnIndex};
9+
use crate::{db::HirDatabase, DebruijnIndex};
1110

1211
use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
1312

@@ -36,34 +35,6 @@ fn create_chalk_solver() -> chalk_solve::Solver<Interner> {
3635
solver_choice.into_solver()
3736
}
3837

39-
/// Collects impls for the given trait in the whole dependency tree of `krate`.
40-
pub(crate) fn impls_for_trait_query(
41-
db: &dyn HirDatabase,
42-
krate: CrateId,
43-
trait_: TraitId,
44-
self_ty_fp: Option<TyFingerprint>,
45-
) -> Arc<[ImplId]> {
46-
// FIXME: We could be a lot smarter here - because of the orphan rules and
47-
// the fact that the trait and the self type need to be in the dependency
48-
// tree of a crate somewhere for an impl to exist, we could skip looking in
49-
// a lot of crates completely
50-
let mut impls = FxHashSet::default();
51-
// We call the query recursively here. On the one hand, this means we can
52-
// reuse results from queries for different crates; on the other hand, this
53-
// will only ever get called for a few crates near the root of the tree (the
54-
// ones the user is editing), so this may actually be a waste of memory. I'm
55-
// doing it like this mainly for simplicity for now.
56-
for dep in &db.crate_graph()[krate].dependencies {
57-
impls.extend(db.impls_for_trait(dep.crate_id, trait_, self_ty_fp).iter());
58-
}
59-
let crate_impl_defs = db.impls_in_crate(krate);
60-
match self_ty_fp {
61-
Some(fp) => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp)),
62-
None => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)),
63-
}
64-
impls.into_iter().collect()
65-
}
66-
6738
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
6839
/// ```rust
6940
/// fn foo<T: Default>(t: T) {}

crates/ra_hir_ty/src/traits/chalk.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,26 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
7474
// Note: Since we're using impls_for_trait, only impls where the trait
7575
// can be resolved should ever reach Chalk. `impl_datum` relies on that
7676
// and will panic if the trait can't be resolved.
77-
let mut result: Vec<_> = self
78-
.db
79-
.impls_for_trait(self.krate, trait_, self_ty_fp)
80-
.iter()
81-
.copied()
82-
.map(Impl::ImplDef)
83-
.map(|impl_| impl_.to_chalk(self.db))
84-
.collect();
77+
let in_deps = self.db.impls_from_deps(self.krate);
78+
let in_self = self.db.impls_in_crate(self.krate);
79+
let impl_maps = [in_deps, in_self];
80+
81+
let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
82+
83+
let mut result: Vec<_> = match self_ty_fp {
84+
Some(fp) => impl_maps
85+
.iter()
86+
.flat_map(|crate_impl_defs| {
87+
crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk)
88+
})
89+
.collect(),
90+
None => impl_maps
91+
.iter()
92+
.flat_map(|crate_impl_defs| {
93+
crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk)
94+
})
95+
.collect(),
96+
};
8597

8698
let arg: Option<Ty> =
8799
parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));

crates/ra_ide_db/src/change.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ impl RootDatabase {
283283
hir::db::GenericPredicatesQuery
284284
hir::db::GenericDefaultsQuery
285285
hir::db::ImplsInCrateQuery
286-
hir::db::ImplsForTraitQuery
287286
hir::db::InternTypeCtorQuery
288287
hir::db::InternTypeParamIdQuery
289288
hir::db::InternChalkImplQuery

0 commit comments

Comments
 (0)