diff options
Diffstat (limited to 'crates/ra_hir_ty/src/utils.rs')
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 91 |
1 files changed, 68 insertions, 23 deletions
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 0b1806a84..508ae9046 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -2,10 +2,11 @@ | |||
2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). | 2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::generics::WherePredicateTarget; | ||
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | adt::VariantData, | 7 | adt::VariantData, |
7 | db::DefDatabase, | 8 | db::DefDatabase, |
8 | generics::{GenericParams, TypeParamData}, | 9 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
9 | path::Path, | 10 | path::Path, |
10 | resolver::{HasResolver, TypeNs}, | 11 | resolver::{HasResolver, TypeNs}, |
11 | type_ref::TypeRef, | 12 | type_ref::TypeRef, |
@@ -19,11 +20,18 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
19 | // lifetime problems, but since there usually shouldn't be more than a | 20 | // lifetime problems, but since there usually shouldn't be more than a |
20 | // few direct traits this should be fine (we could even use some kind of | 21 | // few direct traits this should be fine (we could even use some kind of |
21 | // SmallVec if performance is a concern) | 22 | // SmallVec if performance is a concern) |
22 | db.generic_params(trait_.into()) | 23 | let generic_params = db.generic_params(trait_.into()); |
24 | let trait_self = generic_params.find_trait_self_param(); | ||
25 | generic_params | ||
23 | .where_predicates | 26 | .where_predicates |
24 | .iter() | 27 | .iter() |
25 | .filter_map(|pred| match &pred.type_ref { | 28 | .filter_map(|pred| match &pred.target { |
26 | TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(), | 29 | WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => { |
30 | pred.bound.as_path() | ||
31 | } | ||
32 | WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { | ||
33 | pred.bound.as_path() | ||
34 | } | ||
27 | _ => None, | 35 | _ => None, |
28 | }) | 36 | }) |
29 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { | 37 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { |
@@ -95,41 +103,77 @@ pub(crate) struct Generics { | |||
95 | } | 103 | } |
96 | 104 | ||
97 | impl Generics { | 105 | impl Generics { |
98 | pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { | 106 | pub(crate) fn iter<'a>( |
107 | &'a self, | ||
108 | ) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a { | ||
99 | self.parent_generics | 109 | self.parent_generics |
100 | .as_ref() | 110 | .as_ref() |
101 | .into_iter() | 111 | .into_iter() |
102 | .flat_map(|it| it.params.types.iter()) | 112 | .flat_map(|it| { |
103 | .chain(self.params.types.iter()) | 113 | it.params |
104 | .enumerate() | 114 | .types |
105 | .map(|(i, (_local_id, p))| (i as u32, p)) | 115 | .iter() |
116 | .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)) | ||
117 | }) | ||
118 | .chain( | ||
119 | self.params | ||
120 | .types | ||
121 | .iter() | ||
122 | .map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)), | ||
123 | ) | ||
106 | } | 124 | } |
107 | 125 | ||
108 | pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { | 126 | pub(crate) fn iter_parent<'a>( |
109 | self.parent_generics | 127 | &'a self, |
110 | .as_ref() | 128 | ) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a { |
111 | .into_iter() | 129 | self.parent_generics.as_ref().into_iter().flat_map(|it| { |
112 | .flat_map(|it| it.params.types.iter()) | 130 | it.params |
113 | .enumerate() | 131 | .types |
114 | .map(|(i, (_local_id, p))| (i as u32, p)) | 132 | .iter() |
133 | .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)) | ||
134 | }) | ||
115 | } | 135 | } |
116 | 136 | ||
117 | pub(crate) fn len(&self) -> usize { | 137 | pub(crate) fn len(&self) -> usize { |
118 | self.len_split().0 | 138 | self.len_split().0 |
119 | } | 139 | } |
140 | |||
120 | /// (total, parents, child) | 141 | /// (total, parents, child) |
121 | pub(crate) fn len_split(&self) -> (usize, usize, usize) { | 142 | pub(crate) fn len_split(&self) -> (usize, usize, usize) { |
122 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); | 143 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); |
123 | let child = self.params.types.len(); | 144 | let child = self.params.types.len(); |
124 | (parent + child, parent, child) | 145 | (parent + child, parent, child) |
125 | } | 146 | } |
126 | pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { | 147 | |
127 | self.find_param(param).0 | 148 | /// (parent total, self param, type param list, impl trait) |
149 | pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize) { | ||
150 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); | ||
151 | let self_params = self | ||
152 | .params | ||
153 | .types | ||
154 | .iter() | ||
155 | .filter(|(_, p)| p.provenance == TypeParamProvenance::TraitSelf) | ||
156 | .count(); | ||
157 | let list_params = self | ||
158 | .params | ||
159 | .types | ||
160 | .iter() | ||
161 | .filter(|(_, p)| p.provenance == TypeParamProvenance::TypeParamList) | ||
162 | .count(); | ||
163 | let impl_trait_params = self | ||
164 | .params | ||
165 | .types | ||
166 | .iter() | ||
167 | .filter(|(_, p)| p.provenance == TypeParamProvenance::ArgumentImplTrait) | ||
168 | .count(); | ||
169 | (parent, self_params, list_params, impl_trait_params) | ||
128 | } | 170 | } |
129 | pub(crate) fn param_name(&self, param: TypeParamId) -> Name { | 171 | |
130 | self.find_param(param).1.name.clone() | 172 | pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> { |
173 | Some(self.find_param(param)?.0) | ||
131 | } | 174 | } |
132 | fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { | 175 | |
176 | fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> { | ||
133 | if param.parent == self.def { | 177 | if param.parent == self.def { |
134 | let (idx, (_local_id, data)) = self | 178 | let (idx, (_local_id, data)) = self |
135 | .params | 179 | .params |
@@ -139,9 +183,10 @@ impl Generics { | |||
139 | .find(|(_, (idx, _))| *idx == param.local_id) | 183 | .find(|(_, (idx, _))| *idx == param.local_id) |
140 | .unwrap(); | 184 | .unwrap(); |
141 | let (_total, parent_len, _child) = self.len_split(); | 185 | let (_total, parent_len, _child) = self.len_split(); |
142 | return ((parent_len + idx) as u32, data); | 186 | Some(((parent_len + idx) as u32, data)) |
187 | } else { | ||
188 | self.parent_generics.as_ref().and_then(|g| g.find_param(param)) | ||
143 | } | 189 | } |
144 | self.parent_generics.as_ref().unwrap().find_param(param) | ||
145 | } | 190 | } |
146 | } | 191 | } |
147 | 192 | ||