Skip to content

Commit 4a07923

Browse files
committed
Detangle ty from traits a bit
1 parent 4d753fa commit 4a07923

File tree

5 files changed

+63
-49
lines changed

5 files changed

+63
-49
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use hir_def::{
99
builtin_type::BuiltinType,
1010
docs::Documentation,
1111
per_ns::PerNs,
12-
resolver::{HasResolver, TypeNs},
12+
resolver::HasResolver,
1313
type_ref::{Mutability, TypeRef},
1414
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId,
1515
HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
@@ -28,8 +28,8 @@ use crate::{
2828
expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
2929
ty::display::HirFormatter,
3030
ty::{
31-
self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor,
32-
TypeWalk,
31+
self, utils::all_super_traits, InEnvironment, InferenceResult, Namespace, TraitEnvironment,
32+
TraitRef, Ty, TypeCtor, TypeWalk,
3333
},
3434
CallableDef, Either, HirDisplay, Name, Source,
3535
};
@@ -740,48 +740,6 @@ impl Trait {
740740
db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect()
741741
}
742742

743-
fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
744-
let resolver = self.id.resolver(db);
745-
// returning the iterator directly doesn't easily work because of
746-
// lifetime problems, but since there usually shouldn't be more than a
747-
// few direct traits this should be fine (we could even use some kind of
748-
// SmallVec if performance is a concern)
749-
db.generic_params(self.id.into())
750-
.where_predicates
751-
.iter()
752-
.filter_map(|pred| match &pred.type_ref {
753-
TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
754-
_ => None,
755-
})
756-
.filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
757-
Some(TypeNs::TraitId(t)) => Some(t),
758-
_ => None,
759-
})
760-
.map(Trait::from)
761-
.collect()
762-
}
763-
764-
/// Returns an iterator over the whole super trait hierarchy (including the
765-
/// trait itself).
766-
pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
767-
// we need to take care a bit here to avoid infinite loops in case of cycles
768-
// (i.e. if we have `trait A: B; trait B: A;`)
769-
let mut result = vec![self];
770-
let mut i = 0;
771-
while i < result.len() {
772-
let t = result[i];
773-
// yeah this is quadratic, but trait hierarchies should be flat
774-
// enough that this doesn't matter
775-
for tt in t.direct_super_traits(db) {
776-
if !result.contains(&tt) {
777-
result.push(tt);
778-
}
779-
}
780-
i += 1;
781-
}
782-
result
783-
}
784-
785743
pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
786744
let trait_data = db.trait_data(self.id);
787745
let res =
@@ -794,7 +752,10 @@ impl Trait {
794752
db: &impl HirDatabase,
795753
name: &Name,
796754
) -> Option<TypeAlias> {
797-
self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
755+
all_super_traits(db, self.id)
756+
.into_iter()
757+
.map(Trait::from)
758+
.find_map(|t| t.associated_type_by_name(db, name))
798759
}
799760

800761
pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {

crates/ra_hir/src/ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod op;
99
mod lower;
1010
mod infer;
1111
pub(crate) mod display;
12+
pub(crate) mod utils;
1213

1314
#[cfg(test)]
1415
mod tests;

crates/ra_hir/src/ty/lower.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::{
2828
db::HirDatabase,
2929
ty::{
3030
primitive::{FloatTy, IntTy},
31+
utils::all_super_traits,
3132
Adt,
3233
},
3334
util::make_mut_slice,
@@ -260,7 +261,7 @@ impl Ty {
260261
GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
261262
_ => None,
262263
});
263-
let traits = traits_from_env.flat_map(|t| t.all_super_traits(db));
264+
let traits = traits_from_env.flat_map(|t| all_super_traits(db, t.id)).map(Trait::from);
264265
for t in traits {
265266
if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) {
266267
let substs = Substs::build_for_def(db, t.id)

crates/ra_hir/src/ty/method_resolution.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_hash::FxHashMap;
1616
use crate::{
1717
db::HirDatabase,
1818
ty::primitive::{FloatBitness, Uncertain},
19-
ty::{Ty, TypeCtor},
19+
ty::{utils::all_super_traits, Ty, TypeCtor},
2020
AssocItem, Crate, Function, Mutability, Name, Trait,
2121
};
2222

@@ -249,7 +249,8 @@ fn iterate_trait_method_candidates<T>(
249249
let traits_from_env = env
250250
.trait_predicates_for_self_ty(&ty.value)
251251
.map(|tr| tr.trait_)
252-
.flat_map(|t| t.all_super_traits(db));
252+
.flat_map(|t| all_super_traits(db, t.id))
253+
.map(Trait::from);
253254
let traits = inherent_trait
254255
.chain(traits_from_env)
255256
.chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));

crates/ra_hir/src/ty/utils.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use hir_def::{
2+
db::DefDatabase,
3+
resolver::{HasResolver, TypeNs},
4+
type_ref::TypeRef,
5+
TraitId,
6+
};
7+
use hir_expand::name;
8+
9+
// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
10+
// We should return a `TraitREf` here.
11+
fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
12+
let resolver = trait_.resolver(db);
13+
// returning the iterator directly doesn't easily work because of
14+
// lifetime problems, but since there usually shouldn't be more than a
15+
// few direct traits this should be fine (we could even use some kind of
16+
// SmallVec if performance is a concern)
17+
db.generic_params(trait_.into())
18+
.where_predicates
19+
.iter()
20+
.filter_map(|pred| match &pred.type_ref {
21+
TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
22+
_ => None,
23+
})
24+
.filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
25+
Some(TypeNs::TraitId(t)) => Some(t),
26+
_ => None,
27+
})
28+
.collect()
29+
}
30+
31+
/// Returns an iterator over the whole super trait hierarchy (including the
32+
/// trait itself).
33+
pub(crate) fn all_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
34+
// we need to take care a bit here to avoid infinite loops in case of cycles
35+
// (i.e. if we have `trait A: B; trait B: A;`)
36+
let mut result = vec![trait_];
37+
let mut i = 0;
38+
while i < result.len() {
39+
let t = result[i];
40+
// yeah this is quadratic, but trait hierarchies should be flat
41+
// enough that this doesn't matter
42+
for tt in direct_super_traits(db, t) {
43+
if !result.contains(&tt) {
44+
result.push(tt);
45+
}
46+
}
47+
i += 1;
48+
}
49+
result
50+
}

0 commit comments

Comments
 (0)