aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-09-07 15:39:05 +0100
committerFlorian Diebold <[email protected]>2019-09-07 15:49:57 +0100
commit8fb3cab76c60fbff5ae6f5984ac07b09b42b742c (patch)
treefdf832ba772141368f27d733cd718ee9a599a346 /crates/ra_hir/src/code_model.rs
parent9db34eec209c740ed919afb288f75daa755cd268 (diff)
Fix crash for super trait cycles
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs36
1 files changed, 18 insertions, 18 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 52ee1834f..1bb2f9f28 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,11 +1,8 @@
1pub(crate) mod src; 1pub(crate) mod src;
2pub(crate) mod docs; 2pub(crate) mod docs;
3 3
4use std::iter;
5use std::sync::Arc; 4use std::sync::Arc;
6 5
7use itertools::Itertools;
8
9use ra_db::{CrateId, Edition, FileId, SourceRootId}; 6use ra_db::{CrateId, Edition, FileId, SourceRootId};
10use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 7use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
11 8
@@ -849,20 +846,23 @@ impl Trait {
849 846
850 /// Returns an iterator over the whole super trait hierarchy (including the 847 /// Returns an iterator over the whole super trait hierarchy (including the
851 /// trait itself). 848 /// trait itself).
852 pub fn all_super_traits<'a>( 849 pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
853 self, 850 // we need to take care a bit here to avoid infinite loops in case of cycles
854 db: &'a impl HirDatabase, 851 // (i.e. if we have `trait A: B; trait B: A;`)
855 ) -> impl Iterator<Item = Trait> + 'a { 852 let mut result = vec![self];
856 self.all_super_traits_inner(db).unique() 853 let mut i = 0;
857 } 854 while i < result.len() {
858 855 let t = result[i];
859 fn all_super_traits_inner<'a>( 856 // yeah this is quadratic, but trait hierarchies should be flat
860 self, 857 // enough that this doesn't matter
861 db: &'a impl HirDatabase, 858 for tt in t.direct_super_traits(db) {
862 ) -> impl Iterator<Item = Trait> + 'a { 859 if !result.contains(&tt) {
863 iter::once(self).chain(self.direct_super_traits(db).into_iter().flat_map(move |t| { 860 result.push(tt);
864 iter::once(t).chain(Box::new(t.all_super_traits(db)) as Box<dyn Iterator<Item = Trait>>) 861 }
865 })) 862 }
863 i += 1;
864 }
865 result
866 } 866 }
867 867
868 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { 868 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
@@ -882,7 +882,7 @@ impl Trait {
882 db: &impl HirDatabase, 882 db: &impl HirDatabase,
883 name: &Name, 883 name: &Name,
884 ) -> Option<TypeAlias> { 884 ) -> Option<TypeAlias> {
885 self.all_super_traits(db).find_map(|t| t.associated_type_by_name(db, name)) 885 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
886 } 886 }
887 887
888 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 888 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {