diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 73 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_def/src/type_ref.rs | 42 |
3 files changed, 114 insertions, 11 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index e9c28c730..f765e6edc 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -27,8 +27,16 @@ use crate::{ | |||
27 | /// Data about a generic parameter (to a function, struct, impl, ...). | 27 | /// Data about a generic parameter (to a function, struct, impl, ...). |
28 | #[derive(Clone, PartialEq, Eq, Debug)] | 28 | #[derive(Clone, PartialEq, Eq, Debug)] |
29 | pub struct TypeParamData { | 29 | pub struct TypeParamData { |
30 | pub name: Name, | 30 | pub name: Option<Name>, |
31 | pub default: Option<TypeRef>, | 31 | pub default: Option<TypeRef>, |
32 | pub provenance: TypeParamProvenance, | ||
33 | } | ||
34 | |||
35 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
36 | pub enum TypeParamProvenance { | ||
37 | TypeParamList, | ||
38 | TraitSelf, | ||
39 | ArgumentImplTrait, | ||
32 | } | 40 | } |
33 | 41 | ||
34 | /// Data about the generic parameters of a function, struct, impl, etc. | 42 | /// Data about the generic parameters of a function, struct, impl, etc. |
@@ -45,10 +53,17 @@ pub struct GenericParams { | |||
45 | /// associated type bindings like `Iterator<Item = u32>`. | 53 | /// associated type bindings like `Iterator<Item = u32>`. |
46 | #[derive(Clone, PartialEq, Eq, Debug)] | 54 | #[derive(Clone, PartialEq, Eq, Debug)] |
47 | pub struct WherePredicate { | 55 | pub struct WherePredicate { |
48 | pub type_ref: TypeRef, | 56 | pub target: WherePredicateTarget, |
49 | pub bound: TypeBound, | 57 | pub bound: TypeBound, |
50 | } | 58 | } |
51 | 59 | ||
60 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
61 | pub enum WherePredicateTarget { | ||
62 | TypeRef(TypeRef), | ||
63 | /// For desugared where predicates that can directly refer to a type param. | ||
64 | TypeParam(LocalTypeParamId), | ||
65 | } | ||
66 | |||
52 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; | 67 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; |
53 | 68 | ||
54 | impl GenericParams { | 69 | impl GenericParams { |
@@ -68,6 +83,11 @@ impl GenericParams { | |||
68 | GenericDefId::FunctionId(it) => { | 83 | GenericDefId::FunctionId(it) => { |
69 | let src = it.lookup(db).source(db); | 84 | let src = it.lookup(db).source(db); |
70 | generics.fill(&mut sm, &src.value); | 85 | generics.fill(&mut sm, &src.value); |
86 | // lower `impl Trait` in arguments | ||
87 | let data = db.function_data(it); | ||
88 | for param in &data.params { | ||
89 | generics.fill_implicit_impl_trait_args(param); | ||
90 | } | ||
71 | src.file_id | 91 | src.file_id |
72 | } | 92 | } |
73 | GenericDefId::AdtId(AdtId::StructId(it)) => { | 93 | GenericDefId::AdtId(AdtId::StructId(it)) => { |
@@ -89,8 +109,11 @@ impl GenericParams { | |||
89 | let src = it.lookup(db).source(db); | 109 | let src = it.lookup(db).source(db); |
90 | 110 | ||
91 | // traits get the Self type as an implicit first type parameter | 111 | // traits get the Self type as an implicit first type parameter |
92 | let self_param_id = | 112 | let self_param_id = generics.types.alloc(TypeParamData { |
93 | generics.types.alloc(TypeParamData { name: name![Self], default: None }); | 113 | name: Some(name![Self]), |
114 | default: None, | ||
115 | provenance: TypeParamProvenance::TraitSelf, | ||
116 | }); | ||
94 | sm.insert(self_param_id, Either::Left(src.value.clone())); | 117 | sm.insert(self_param_id, Either::Left(src.value.clone())); |
95 | // add super traits as bounds on Self | 118 | // add super traits as bounds on Self |
96 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 119 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
@@ -142,7 +165,11 @@ impl GenericParams { | |||
142 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 165 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
143 | // FIXME: Use `Path::from_src` | 166 | // FIXME: Use `Path::from_src` |
144 | let default = type_param.default_type().map(TypeRef::from_ast); | 167 | let default = type_param.default_type().map(TypeRef::from_ast); |
145 | let param = TypeParamData { name: name.clone(), default }; | 168 | let param = TypeParamData { |
169 | name: Some(name.clone()), | ||
170 | default, | ||
171 | provenance: TypeParamProvenance::TypeParamList, | ||
172 | }; | ||
146 | let param_id = self.types.alloc(param); | 173 | let param_id = self.types.alloc(param); |
147 | sm.insert(param_id, Either::Right(type_param.clone())); | 174 | sm.insert(param_id, Either::Right(type_param.clone())); |
148 | 175 | ||
@@ -170,11 +197,43 @@ impl GenericParams { | |||
170 | return; | 197 | return; |
171 | } | 198 | } |
172 | let bound = TypeBound::from_ast(bound); | 199 | let bound = TypeBound::from_ast(bound); |
173 | self.where_predicates.push(WherePredicate { type_ref, bound }); | 200 | self.where_predicates |
201 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); | ||
202 | } | ||
203 | |||
204 | fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { | ||
205 | type_ref.walk(&mut |type_ref| { | ||
206 | if let TypeRef::ImplTrait(bounds) = type_ref { | ||
207 | let param = TypeParamData { | ||
208 | name: None, | ||
209 | default: None, | ||
210 | provenance: TypeParamProvenance::ArgumentImplTrait, | ||
211 | }; | ||
212 | let param_id = self.types.alloc(param); | ||
213 | for bound in bounds { | ||
214 | self.where_predicates.push(WherePredicate { | ||
215 | target: WherePredicateTarget::TypeParam(param_id), | ||
216 | bound: bound.clone(), | ||
217 | }); | ||
218 | } | ||
219 | } | ||
220 | }); | ||
174 | } | 221 | } |
175 | 222 | ||
176 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 223 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
177 | self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) | 224 | self.types |
225 | .iter() | ||
226 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) | ||
227 | } | ||
228 | |||
229 | pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> { | ||
230 | self.types.iter().find_map(|(id, p)| { | ||
231 | if p.provenance == TypeParamProvenance::TraitSelf { | ||
232 | Some(id) | ||
233 | } else { | ||
234 | None | ||
235 | } | ||
236 | }) | ||
178 | } | 237 | } |
179 | } | 238 | } |
180 | 239 | ||
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index f7bac5801..05cf4646a 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -490,10 +490,12 @@ impl Scope { | |||
490 | } | 490 | } |
491 | Scope::GenericParams { params, def } => { | 491 | Scope::GenericParams { params, def } => { |
492 | for (local_id, param) in params.types.iter() { | 492 | for (local_id, param) in params.types.iter() { |
493 | f( | 493 | if let Some(name) = ¶m.name { |
494 | param.name.clone(), | 494 | f( |
495 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), | 495 | name.clone(), |
496 | ) | 496 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), |
497 | ) | ||
498 | } | ||
497 | } | 499 | } |
498 | } | 500 | } |
499 | Scope::ImplBlockScope(i) => { | 501 | Scope::ImplBlockScope(i) => { |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 5f10e9a88..102fdb13d 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -124,6 +124,48 @@ impl TypeRef { | |||
124 | pub(crate) fn unit() -> TypeRef { | 124 | pub(crate) fn unit() -> TypeRef { |
125 | TypeRef::Tuple(Vec::new()) | 125 | TypeRef::Tuple(Vec::new()) |
126 | } | 126 | } |
127 | |||
128 | pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { | ||
129 | go(self, f); | ||
130 | |||
131 | fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { | ||
132 | f(type_ref); | ||
133 | match type_ref { | ||
134 | TypeRef::Fn(types) | TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), | ||
135 | TypeRef::RawPtr(type_ref, _) | ||
136 | | TypeRef::Reference(type_ref, _) | ||
137 | | TypeRef::Array(type_ref) | ||
138 | | TypeRef::Slice(type_ref) => go(&type_ref, f), | ||
139 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { | ||
140 | for bound in bounds { | ||
141 | match bound { | ||
142 | TypeBound::Path(path) => go_path(path, f), | ||
143 | TypeBound::Error => (), | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | TypeRef::Path(path) => go_path(path, f), | ||
148 | TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {} | ||
149 | }; | ||
150 | } | ||
151 | |||
152 | fn go_path(path: &Path, f: &mut impl FnMut(&TypeRef)) { | ||
153 | if let Some(type_ref) = path.type_anchor() { | ||
154 | go(type_ref, f); | ||
155 | } | ||
156 | for segment in path.segments().iter() { | ||
157 | if let Some(args_and_bindings) = segment.args_and_bindings { | ||
158 | for arg in &args_and_bindings.args { | ||
159 | let crate::path::GenericArg::Type(type_ref) = arg; | ||
160 | go(type_ref, f); | ||
161 | } | ||
162 | for (_, type_ref) in &args_and_bindings.bindings { | ||
163 | go(type_ref, f); | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | } | ||
127 | } | 169 | } |
128 | 170 | ||
129 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { | 171 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { |