aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-11-26 13:59:24 +0000
committerAleksey Kladov <[email protected]>2019-11-26 14:44:43 +0000
commit4a0792362e2c6cae2809520da454471d5a917384 (patch)
treee0205440b58772a43f13e2a4c547f1b7008efe46 /crates/ra_hir/src/ty
parent4d753fa6f514ea1105c25ace91201c5324ee0b92 (diff)
Detangle ty from traits a bit
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/lower.rs3
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs5
-rw-r--r--crates/ra_hir/src/ty/utils.rs50
3 files changed, 55 insertions, 3 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 2d23890a5..9e3afabe0 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -28,6 +28,7 @@ use crate::{
28 db::HirDatabase, 28 db::HirDatabase,
29 ty::{ 29 ty::{
30 primitive::{FloatTy, IntTy}, 30 primitive::{FloatTy, IntTy},
31 utils::all_super_traits,
31 Adt, 32 Adt,
32 }, 33 },
33 util::make_mut_slice, 34 util::make_mut_slice,
@@ -260,7 +261,7 @@ impl Ty {
260 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), 261 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
261 _ => None, 262 _ => None,
262 }); 263 });
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);
264 for t in traits { 265 for t in traits {
265 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 266 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) {
266 let substs = Substs::build_for_def(db, t.id) 267 let substs = Substs::build_for_def(db, t.id)
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 489fcd64b..0e18684ed 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -16,7 +16,7 @@ use rustc_hash::FxHashMap;
16use crate::{ 16use crate::{
17 db::HirDatabase, 17 db::HirDatabase,
18 ty::primitive::{FloatBitness, Uncertain}, 18 ty::primitive::{FloatBitness, Uncertain},
19 ty::{Ty, TypeCtor}, 19 ty::{utils::all_super_traits, Ty, TypeCtor},
20 AssocItem, Crate, Function, Mutability, Name, Trait, 20 AssocItem, Crate, Function, Mutability, Name, Trait,
21}; 21};
22 22
@@ -249,7 +249,8 @@ fn iterate_trait_method_candidates<T>(
249 let traits_from_env = env 249 let traits_from_env = env
250 .trait_predicates_for_self_ty(&ty.value) 250 .trait_predicates_for_self_ty(&ty.value)
251 .map(|tr| tr.trait_) 251 .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);
253 let traits = inherent_trait 254 let traits = inherent_trait
254 .chain(traits_from_env) 255 .chain(traits_from_env)
255 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); 256 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));
diff --git a/crates/ra_hir/src/ty/utils.rs b/crates/ra_hir/src/ty/utils.rs
new file mode 100644
index 000000000..345fa9430
--- /dev/null
+++ b/crates/ra_hir/src/ty/utils.rs
@@ -0,0 +1,50 @@
1use hir_def::{
2 db::DefDatabase,
3 resolver::{HasResolver, TypeNs},
4 type_ref::TypeRef,
5 TraitId,
6};
7use 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.
11fn 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).
33pub(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}