diff options
Diffstat (limited to 'crates/ra_hir_def/src/generics.rs')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index e9c28c730..7553d8a87 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. |
@@ -68,6 +76,11 @@ impl GenericParams { | |||
68 | GenericDefId::FunctionId(it) => { | 76 | GenericDefId::FunctionId(it) => { |
69 | let src = it.lookup(db).source(db); | 77 | let src = it.lookup(db).source(db); |
70 | generics.fill(&mut sm, &src.value); | 78 | generics.fill(&mut sm, &src.value); |
79 | // lower `impl Trait` in arguments | ||
80 | let data = db.function_data(it); | ||
81 | for param in &data.params { | ||
82 | generics.fill_implicit_impl_trait_args(param); | ||
83 | } | ||
71 | src.file_id | 84 | src.file_id |
72 | } | 85 | } |
73 | GenericDefId::AdtId(AdtId::StructId(it)) => { | 86 | GenericDefId::AdtId(AdtId::StructId(it)) => { |
@@ -89,8 +102,11 @@ impl GenericParams { | |||
89 | let src = it.lookup(db).source(db); | 102 | let src = it.lookup(db).source(db); |
90 | 103 | ||
91 | // traits get the Self type as an implicit first type parameter | 104 | // traits get the Self type as an implicit first type parameter |
92 | let self_param_id = | 105 | let self_param_id = generics.types.alloc(TypeParamData { |
93 | generics.types.alloc(TypeParamData { name: name![Self], default: None }); | 106 | name: Some(name![Self]), |
107 | default: None, | ||
108 | provenance: TypeParamProvenance::TraitSelf, | ||
109 | }); | ||
94 | sm.insert(self_param_id, Either::Left(src.value.clone())); | 110 | sm.insert(self_param_id, Either::Left(src.value.clone())); |
95 | // add super traits as bounds on Self | 111 | // add super traits as bounds on Self |
96 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 112 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
@@ -142,7 +158,11 @@ impl GenericParams { | |||
142 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 158 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
143 | // FIXME: Use `Path::from_src` | 159 | // FIXME: Use `Path::from_src` |
144 | let default = type_param.default_type().map(TypeRef::from_ast); | 160 | let default = type_param.default_type().map(TypeRef::from_ast); |
145 | let param = TypeParamData { name: name.clone(), default }; | 161 | let param = TypeParamData { |
162 | name: Some(name.clone()), | ||
163 | default, | ||
164 | provenance: TypeParamProvenance::TypeParamList, | ||
165 | }; | ||
146 | let param_id = self.types.alloc(param); | 166 | let param_id = self.types.alloc(param); |
147 | sm.insert(param_id, Either::Right(type_param.clone())); | 167 | sm.insert(param_id, Either::Right(type_param.clone())); |
148 | 168 | ||
@@ -173,8 +193,23 @@ impl GenericParams { | |||
173 | self.where_predicates.push(WherePredicate { type_ref, bound }); | 193 | self.where_predicates.push(WherePredicate { type_ref, bound }); |
174 | } | 194 | } |
175 | 195 | ||
196 | fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { | ||
197 | type_ref.walk(&mut |type_ref| { | ||
198 | if let TypeRef::ImplTrait(_) = type_ref { | ||
199 | let param = TypeParamData { | ||
200 | name: None, | ||
201 | default: None, | ||
202 | provenance: TypeParamProvenance::ArgumentImplTrait, | ||
203 | }; | ||
204 | let _param_id = self.types.alloc(param); | ||
205 | } | ||
206 | }); | ||
207 | } | ||
208 | |||
176 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 209 | 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 }) | 210 | self.types |
211 | .iter() | ||
212 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) | ||
178 | } | 213 | } |
179 | } | 214 | } |
180 | 215 | ||