aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/utils.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-02-22 12:14:39 +0000
committerFlorian Diebold <[email protected]>2020-02-22 12:14:39 +0000
commit3e106c77ff76c39be49444165eac805d32666e41 (patch)
tree7f136356bb7edb610233a2821be0b755725ed03a /crates/ra_hir_ty/src/utils.rs
parentc2000257941956cd4c4365d6eb6cdbc1b16e929c (diff)
Rework find_super_trait_path to protect against cycles
Diffstat (limited to 'crates/ra_hir_ty/src/utils.rs')
-rw-r--r--crates/ra_hir_ty/src/utils.rs33
1 files changed, 22 insertions, 11 deletions
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index 0d1583c39..463fd65b4 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -62,25 +62,36 @@ pub(super) fn all_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<Tr
62 result 62 result
63} 63}
64 64
65/// Finds a path from a trait to one of its descendant traits. Returns an empty 65/// Finds a path from a trait to one of its super traits. Returns an empty
66/// vector if there is no path. 66/// vector if there is no path.
67pub(super) fn find_super_trait_path( 67pub(super) fn find_super_trait_path(
68 db: &impl DefDatabase, 68 db: &impl DefDatabase,
69 super_trait: TraitId,
70 trait_: TraitId, 69 trait_: TraitId,
70 super_trait: TraitId,
71) -> Vec<TraitId> { 71) -> Vec<TraitId> {
72 if trait_ == super_trait { 72 let mut result = Vec::with_capacity(2);
73 return vec![trait_]; 73 result.push(trait_);
74 } 74 return if go(db, super_trait, &mut result) { result } else { Vec::new() };
75
76 fn go(db: &impl DefDatabase, super_trait: TraitId, path: &mut Vec<TraitId>) -> bool {
77 let trait_ = *path.last().unwrap();
78 if trait_ == super_trait {
79 return true;
80 }
75 81
76 for tt in direct_super_traits(db, trait_) { 82 for tt in direct_super_traits(db, trait_) {
77 let mut path = find_super_trait_path(db, super_trait, tt); 83 if path.contains(&tt) {
78 if !path.is_empty() { 84 continue;
79 path.push(trait_); 85 }
80 return path; 86 path.push(tt);
87 if go(db, super_trait, path) {
88 return true;
89 } else {
90 path.pop();
91 }
81 } 92 }
93 false
82 } 94 }
83 Vec::new()
84} 95}
85 96
86pub(super) fn associated_type_by_name_including_super_traits( 97pub(super) fn associated_type_by_name_including_super_traits(