Skip to content

Commit 6bde542

Browse files
author
Jonas Schievink
committed
Split CrateImplDefs in inherent and trait impls
This makes the intention of inherent vs. trait impls somewhat more clear and also fixes (?) an issue where trait impls with an unresolved trait were added as inherent impls instead (hence the test changes).
1 parent 07ba986 commit 6bde542

File tree

7 files changed

+130
-118
lines changed

7 files changed

+130
-118
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,12 +1053,14 @@ pub struct ImplDef {
10531053

10541054
impl ImplDef {
10551055
pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> {
1056-
let impls = db.impls_in_crate(krate.id);
1057-
impls.all_impls().map(Self::from).collect()
1056+
let inherent = db.inherent_impls_in_crate(krate.id);
1057+
let trait_ = db.trait_impls_in_crate(krate.id);
1058+
1059+
inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
10581060
}
10591061
pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> {
1060-
let impls = db.impls_in_crate(krate.id);
1061-
impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect()
1062+
let impls = db.trait_impls_in_crate(krate.id);
1063+
impls.for_trait(trait_.id).map(Self::from).collect()
10621064
}
10631065

10641066
pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
@@ -1303,10 +1305,10 @@ impl Type {
13031305
mut callback: impl FnMut(AssocItem) -> Option<T>,
13041306
) -> Option<T> {
13051307
for krate in self.ty.value.def_crates(db, krate.id)? {
1306-
let impls = db.impls_in_crate(krate);
1308+
let impls = db.inherent_impls_in_crate(krate);
13071309

1308-
for impl_def in impls.lookup_impl_defs(&self.ty.value) {
1309-
for &item in db.impl_data(impl_def).items.iter() {
1310+
for impl_def in impls.for_self_ty(&self.ty.value) {
1311+
for &item in db.impl_data(*impl_def).items.iter() {
13101312
if let Some(result) = callback(item.into()) {
13111313
return Some(result);
13121314
}

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, ImplsFromDepsQuery,
20-
ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery,
21-
InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
22-
TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery,
19+
HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery,
20+
InherentImplsInCrateQuery, InternAssocTyValueQuery, InternChalkImplQuery, InternTypeCtorQuery,
21+
InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, TraitDatumQuery,
22+
TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, ValueTyQuery,
2323
};
2424

2525
#[test]

crates/ra_hir_ty/src/db.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
1111
use ra_prof::profile;
1212

1313
use crate::{
14-
method_resolution::CrateImplDefs,
14+
method_resolution::{InherentImpls, TraitImpls},
1515
traits::{chalk, AssocTyValue, Impl},
1616
Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
1717
ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
@@ -67,11 +67,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
6767
#[salsa::invoke(crate::lower::generic_defaults_query)]
6868
fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>;
6969

70-
#[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
71-
fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
70+
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
71+
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
7272

73-
#[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)]
74-
fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>;
73+
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
74+
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
75+
76+
#[salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
77+
fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<TraitImpls>;
7578

7679
// Interned IDs for Chalk integration
7780
#[salsa::interned]

crates/ra_hir_ty/src/method_resolution.rs

Lines changed: 98 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -38,127 +38,131 @@ impl TyFingerprint {
3838
}
3939
}
4040

41-
/// A queryable and mergeable collection of impls.
42-
#[derive(Debug, PartialEq, Eq)]
43-
pub struct CrateImplDefs {
44-
inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
45-
impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
41+
/// Trait impls defined or available in some crate.
42+
#[derive(Debug, Eq, PartialEq)]
43+
pub struct TraitImpls {
44+
// If the `Option<TyFingerprint>` is `None`, the impl may apply to any self type.
45+
map: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
4646
}
4747

48-
impl CrateImplDefs {
49-
pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
50-
let _p = profile("impls_in_crate_query");
51-
let mut res = CrateImplDefs {
52-
inherent_impls: FxHashMap::default(),
53-
impls_by_trait: FxHashMap::default(),
54-
};
55-
res.fill(db, krate);
48+
impl TraitImpls {
49+
pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
50+
let _p = profile("trait_impls_in_crate_query");
51+
let mut impls = Self { map: FxHashMap::default() };
5652

57-
Arc::new(res)
53+
let crate_def_map = db.crate_def_map(krate);
54+
for (_module_id, module_data) in crate_def_map.modules.iter() {
55+
for impl_id in module_data.scope.impls() {
56+
let target_trait = match db.impl_trait(impl_id) {
57+
Some(tr) => tr.value.trait_,
58+
None => continue,
59+
};
60+
let self_ty = db.impl_self_ty(impl_id);
61+
let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
62+
impls
63+
.map
64+
.entry(target_trait)
65+
.or_default()
66+
.entry(self_ty_fp)
67+
.or_default()
68+
.push(impl_id);
69+
}
70+
}
71+
72+
Arc::new(impls)
5873
}
5974

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-
let _p = profile("impls_from_deps_query");
75+
pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
76+
let _p = profile("trait_impls_in_deps_query");
6977
let crate_graph = db.crate_graph();
70-
let mut res = CrateImplDefs {
71-
inherent_impls: FxHashMap::default(),
72-
impls_by_trait: FxHashMap::default(),
73-
};
78+
let mut res = Self { map: FxHashMap::default() };
7479

7580
for krate in crate_graph.transitive_deps(krate) {
76-
res.merge(&db.impls_in_crate(krate));
81+
res.merge(&db.trait_impls_in_crate(krate));
7782
}
7883

7984
Arc::new(res)
8085
}
8186

82-
fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
83-
let crate_def_map = db.crate_def_map(krate);
84-
for (_module_id, module_data) in crate_def_map.modules.iter() {
85-
for impl_id in module_data.scope.impls() {
86-
match db.impl_trait(impl_id) {
87-
Some(tr) => {
88-
let self_ty = db.impl_self_ty(impl_id);
89-
let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
90-
self.impls_by_trait
91-
.entry(tr.value.trait_)
92-
.or_default()
93-
.entry(self_ty_fp)
94-
.or_default()
95-
.push(impl_id);
96-
}
97-
None => {
98-
let self_ty = db.impl_self_ty(impl_id);
99-
if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
100-
self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
101-
}
102-
}
103-
}
104-
}
105-
}
106-
}
107-
10887
fn merge(&mut self, other: &Self) {
109-
for (fp, impls) in &other.inherent_impls {
110-
let vec = self.inherent_impls.entry(*fp).or_default();
111-
vec.extend(impls);
112-
}
113-
114-
for (trait_, other_map) in &other.impls_by_trait {
115-
let map = self.impls_by_trait.entry(*trait_).or_default();
88+
for (trait_, other_map) in &other.map {
89+
let map = self.map.entry(*trait_).or_default();
11690
for (fp, impls) in other_map {
11791
let vec = map.entry(*fp).or_default();
11892
vec.extend(impls);
11993
}
12094
}
12195
}
12296

123-
pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
124-
let fingerprint = TyFingerprint::for_impl(ty);
125-
fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
126-
}
127-
128-
pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
129-
self.impls_by_trait
130-
.get(&tr)
97+
/// Queries all impls of the given trait.
98+
pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
99+
self.map
100+
.get(&trait_)
131101
.into_iter()
132-
.flat_map(|m| m.values().flat_map(|v| v.iter().copied()))
102+
.flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
133103
}
134104

135-
pub fn lookup_impl_defs_for_trait_and_ty(
105+
/// Queries all impls of `trait_` that may apply to `self_ty`.
106+
pub fn for_trait_and_self_ty(
136107
&self,
137-
tr: TraitId,
138-
fp: TyFingerprint,
108+
trait_: TraitId,
109+
self_ty: TyFingerprint,
139110
) -> impl Iterator<Item = ImplId> + '_ {
140-
self.impls_by_trait
141-
.get(&tr)
142-
.and_then(|m| m.get(&Some(fp)))
111+
self.map
112+
.get(&trait_)
143113
.into_iter()
144-
.flatten()
145-
.copied()
146-
.chain(
147-
self.impls_by_trait
148-
.get(&tr)
149-
.and_then(|m| m.get(&None))
150-
.into_iter()
151-
.flatten()
152-
.copied(),
153-
)
114+
.flat_map(move |map| map.get(&None).into_iter().chain(map.get(&Some(self_ty))))
115+
.flat_map(|v| v.iter().copied())
116+
}
117+
118+
pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
119+
self.map.values().flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
120+
}
121+
}
122+
123+
/// Inherent impls defined in some crate.
124+
///
125+
/// Inherent impls can only be defined in the crate that also defines the self type of the impl
126+
/// (note that some primitives are considered to be defined by both libcore and liballoc).
127+
///
128+
/// This makes inherent impl lookup easier than trait impl lookup since we only have to consider a
129+
/// single crate.
130+
#[derive(Debug, Eq, PartialEq)]
131+
pub struct InherentImpls {
132+
map: FxHashMap<TyFingerprint, Vec<ImplId>>,
133+
}
134+
135+
impl InherentImpls {
136+
pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
137+
let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default();
138+
139+
let crate_def_map = db.crate_def_map(krate);
140+
for (_module_id, module_data) in crate_def_map.modules.iter() {
141+
for impl_id in module_data.scope.impls() {
142+
let data = db.impl_data(impl_id);
143+
if data.target_trait.is_some() {
144+
continue;
145+
}
146+
147+
let self_ty = db.impl_self_ty(impl_id);
148+
if let Some(fp) = TyFingerprint::for_impl(&self_ty.value) {
149+
map.entry(fp).or_default().push(impl_id);
150+
}
151+
}
152+
}
153+
154+
Arc::new(Self { map })
155+
}
156+
157+
pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
158+
match TyFingerprint::for_impl(self_ty) {
159+
Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
160+
None => &[],
161+
}
154162
}
155163

156-
pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
157-
self.inherent_impls
158-
.values()
159-
.chain(self.impls_by_trait.values().flat_map(|m| m.values()))
160-
.flatten()
161-
.copied()
164+
pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
165+
self.map.values().flat_map(|v| v.iter().copied())
162166
}
163167
}
164168

@@ -515,9 +519,9 @@ fn iterate_inherent_methods(
515519
None => return false,
516520
};
517521
for krate in def_crates {
518-
let impls = db.impls_in_crate(krate);
522+
let impls = db.inherent_impls_in_crate(krate);
519523

520-
for impl_def in impls.lookup_impl_defs(&self_ty.value) {
524+
for &impl_def in impls.for_self_ty(&self_ty.value) {
521525
for &item in db.impl_data(impl_def).items.iter() {
522526
if !is_valid_candidate(db, name, receiver_ty, item, self_ty) {
523527
continue;

crates/ra_hir_ty/src/traits/chalk.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
7777
// Note: Since we're using impls_for_trait, only impls where the trait
7878
// can be resolved should ever reach Chalk. `impl_datum` relies on that
7979
// and will panic if the trait can't be resolved.
80-
let in_deps = self.db.impls_from_deps(self.krate);
81-
let in_self = self.db.impls_in_crate(self.krate);
80+
let in_deps = self.db.trait_impls_in_deps(self.krate);
81+
let in_self = self.db.trait_impls_in_crate(self.krate);
8282
let impl_maps = [in_deps, in_self];
8383

8484
let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
@@ -87,14 +87,12 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
8787
Some(fp) => impl_maps
8888
.iter()
8989
.flat_map(|crate_impl_defs| {
90-
crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk)
90+
crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk)
9191
})
9292
.collect(),
9393
None => impl_maps
9494
.iter()
95-
.flat_map(|crate_impl_defs| {
96-
crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk)
97-
})
95+
.flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk))
9896
.collect(),
9997
};
10098

crates/ra_ide/src/goto_implementation.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ impl T for &Foo {}
219219
#[derive(Copy)]
220220
//^^^^^^^^^^^^^^^
221221
struct Foo<|>;
222+
223+
mod marker {
224+
trait Copy {}
225+
}
222226
"#,
223227
);
224228
}

crates/ra_ide_db/src/change.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,9 @@ impl RootDatabase {
243243
hir::db::GenericPredicatesForParamQuery
244244
hir::db::GenericPredicatesQuery
245245
hir::db::GenericDefaultsQuery
246-
hir::db::ImplsInCrateQuery
247-
hir::db::ImplsFromDepsQuery
246+
hir::db::InherentImplsInCrateQuery
247+
hir::db::TraitImplsInCrateQuery
248+
hir::db::TraitImplsInDepsQuery
248249
hir::db::InternTypeCtorQuery
249250
hir::db::InternTypeParamIdQuery
250251
hir::db::InternChalkImplQuery

0 commit comments

Comments
 (0)