aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs57
1 files changed, 55 insertions, 2 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index f7efc1b66..1bb2f9f28 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -820,7 +820,52 @@ impl Trait {
820 self.trait_data(db).items().to_vec() 820 self.trait_data(db).items().to_vec()
821 } 821 }
822 822
823 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: Name) -> Option<TypeAlias> { 823 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
824 let resolver = self.resolver(db);
825 // returning the iterator directly doesn't easily work because of
826 // lifetime problems, but since there usually shouldn't be more than a
827 // few direct traits this should be fine (we could even use some kind of
828 // SmallVec if performance is a concern)
829 self.generic_params(db)
830 .where_predicates
831 .iter()
832 .filter_map(|pred| match &pred.type_ref {
833 TypeRef::Path(p) if p.as_ident() == Some(&crate::name::SELF_TYPE) => {
834 pred.bound.as_path()
835 }
836 _ => None,
837 })
838 .filter_map(|path| {
839 match resolver.resolve_path_without_assoc_items(db, path).take_types() {
840 Some(crate::Resolution::Def(ModuleDef::Trait(t))) => Some(t),
841 _ => None,
842 }
843 })
844 .collect()
845 }
846
847 /// Returns an iterator over the whole super trait hierarchy (including the
848 /// trait itself).
849 pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
850 // we need to take care a bit here to avoid infinite loops in case of cycles
851 // (i.e. if we have `trait A: B; trait B: A;`)
852 let mut result = vec![self];
853 let mut i = 0;
854 while i < result.len() {
855 let t = result[i];
856 // yeah this is quadratic, but trait hierarchies should be flat
857 // enough that this doesn't matter
858 for tt in t.direct_super_traits(db) {
859 if !result.contains(&tt) {
860 result.push(tt);
861 }
862 }
863 i += 1;
864 }
865 result
866 }
867
868 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
824 let trait_data = self.trait_data(db); 869 let trait_data = self.trait_data(db);
825 trait_data 870 trait_data
826 .items() 871 .items()
@@ -829,7 +874,15 @@ impl Trait {
829 TraitItem::TypeAlias(t) => Some(*t), 874 TraitItem::TypeAlias(t) => Some(*t),
830 _ => None, 875 _ => None,
831 }) 876 })
832 .find(|t| t.name(db) == name) 877 .find(|t| &t.name(db) == name)
878 }
879
880 pub fn associated_type_by_name_including_super_traits(
881 self,
882 db: &impl HirDatabase,
883 name: &Name,
884 ) -> Option<TypeAlias> {
885 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
833 } 886 }
834 887
835 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 888 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {