diff options
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 53 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/utils.rs | 50 |
5 files changed, 63 insertions, 49 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 821f919d4..9930cff66 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -9,7 +9,7 @@ use hir_def::{ | |||
9 | builtin_type::BuiltinType, | 9 | builtin_type::BuiltinType, |
10 | docs::Documentation, | 10 | docs::Documentation, |
11 | per_ns::PerNs, | 11 | per_ns::PerNs, |
12 | resolver::{HasResolver, TypeNs}, | 12 | resolver::HasResolver, |
13 | type_ref::{Mutability, TypeRef}, | 13 | type_ref::{Mutability, TypeRef}, |
14 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, | 14 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, |
15 | HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, | 15 | HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, |
@@ -28,8 +28,8 @@ use crate::{ | |||
28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, | 28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, |
29 | ty::display::HirFormatter, | 29 | ty::display::HirFormatter, |
30 | ty::{ | 30 | ty::{ |
31 | self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor, | 31 | self, utils::all_super_traits, InEnvironment, InferenceResult, Namespace, TraitEnvironment, |
32 | TypeWalk, | 32 | TraitRef, Ty, TypeCtor, TypeWalk, |
33 | }, | 33 | }, |
34 | CallableDef, Either, HirDisplay, Name, Source, | 34 | CallableDef, Either, HirDisplay, Name, Source, |
35 | }; | 35 | }; |
@@ -740,48 +740,6 @@ impl Trait { | |||
740 | db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect() | 740 | db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect() |
741 | } | 741 | } |
742 | 742 | ||
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 | |||
785 | pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { | 743 | pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { |
786 | let trait_data = db.trait_data(self.id); | 744 | let trait_data = db.trait_data(self.id); |
787 | let res = | 745 | let res = |
@@ -794,7 +752,10 @@ impl Trait { | |||
794 | db: &impl HirDatabase, | 752 | db: &impl HirDatabase, |
795 | name: &Name, | 753 | name: &Name, |
796 | ) -> Option<TypeAlias> { | 754 | ) -> 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)) | ||
798 | } | 759 | } |
799 | 760 | ||
800 | pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { | 761 | pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index bd03055b9..2a2dc26b4 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -9,6 +9,7 @@ mod op; | |||
9 | mod lower; | 9 | mod lower; |
10 | mod infer; | 10 | mod infer; |
11 | pub(crate) mod display; | 11 | pub(crate) mod display; |
12 | pub(crate) mod utils; | ||
12 | 13 | ||
13 | #[cfg(test)] | 14 | #[cfg(test)] |
14 | mod tests; | 15 | mod tests; |
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; | |||
16 | use crate::{ | 16 | use 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 @@ | |||
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 | } | ||