diff options
Diffstat (limited to 'crates/hir_def/src/generics.rs')
-rw-r--r-- | crates/hir_def/src/generics.rs | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 835fe3fbd..5189c7e9f 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | keys, | 21 | keys, |
22 | src::HasChildSource, | 22 | src::HasChildSource, |
23 | src::HasSource, | 23 | src::HasSource, |
24 | type_ref::{TypeBound, TypeRef}, | 24 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
25 | AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, | 25 | AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -33,6 +33,12 @@ pub struct TypeParamData { | |||
33 | pub provenance: TypeParamProvenance, | 33 | pub provenance: TypeParamProvenance, |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Data about a generic parameter (to a function, struct, impl, ...). | ||
37 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
38 | pub struct LifetimeParamData { | ||
39 | pub name: Name, | ||
40 | } | ||
41 | |||
36 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 42 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
37 | pub enum TypeParamProvenance { | 43 | pub enum TypeParamProvenance { |
38 | TypeParamList, | 44 | TypeParamList, |
@@ -44,7 +50,7 @@ pub enum TypeParamProvenance { | |||
44 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 50 | #[derive(Clone, PartialEq, Eq, Debug, Default)] |
45 | pub struct GenericParams { | 51 | pub struct GenericParams { |
46 | pub types: Arena<TypeParamData>, | 52 | pub types: Arena<TypeParamData>, |
47 | // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>, | 53 | pub lifetimes: Arena<LifetimeParamData>, |
48 | pub where_predicates: Vec<WherePredicate>, | 54 | pub where_predicates: Vec<WherePredicate>, |
49 | } | 55 | } |
50 | 56 | ||
@@ -53,16 +59,17 @@ pub struct GenericParams { | |||
53 | /// It might still result in multiple actual predicates though, because of | 59 | /// It might still result in multiple actual predicates though, because of |
54 | /// associated type bindings like `Iterator<Item = u32>`. | 60 | /// associated type bindings like `Iterator<Item = u32>`. |
55 | #[derive(Clone, PartialEq, Eq, Debug)] | 61 | #[derive(Clone, PartialEq, Eq, Debug)] |
56 | pub struct WherePredicate { | 62 | pub enum WherePredicate { |
57 | pub target: WherePredicateTarget, | 63 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, |
58 | pub bound: TypeBound, | 64 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, |
59 | } | 65 | } |
60 | 66 | ||
61 | #[derive(Clone, PartialEq, Eq, Debug)] | 67 | #[derive(Clone, PartialEq, Eq, Debug)] |
62 | pub enum WherePredicateTarget { | 68 | pub enum WherePredicateTypeTarget { |
63 | TypeRef(TypeRef), | 69 | TypeRef(TypeRef), |
64 | /// For desugared where predicates that can directly refer to a type param. | 70 | /// For desugared where predicates that can directly refer to a type param. |
65 | TypeParam(LocalTypeParamId), | 71 | TypeParam(LocalTypeParamId), |
72 | // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef) | ||
66 | } | 73 | } |
67 | 74 | ||
68 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; | 75 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; |
@@ -123,7 +130,7 @@ impl GenericParams { | |||
123 | } | 130 | } |
124 | 131 | ||
125 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { | 132 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
126 | let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; | 133 | let mut generics = GenericParams::default(); |
127 | let mut sm = ArenaMap::default(); | 134 | let mut sm = ArenaMap::default(); |
128 | 135 | ||
129 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 136 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
@@ -171,7 +178,7 @@ impl GenericParams { | |||
171 | // add super traits as bounds on Self | 178 | // add super traits as bounds on Self |
172 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 179 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
173 | let self_param = TypeRef::Path(name![Self].into()); | 180 | let self_param = TypeRef::Path(name![Self].into()); |
174 | generics.fill_bounds(&lower_ctx, &src.value, self_param); | 181 | generics.fill_bounds(&lower_ctx, &src.value, Either::Left(self_param)); |
175 | 182 | ||
176 | generics.fill(&lower_ctx, &mut sm, &src.value); | 183 | generics.fill(&lower_ctx, &mut sm, &src.value); |
177 | src.file_id | 184 | src.file_id |
@@ -218,12 +225,12 @@ impl GenericParams { | |||
218 | &mut self, | 225 | &mut self, |
219 | lower_ctx: &LowerCtx, | 226 | lower_ctx: &LowerCtx, |
220 | node: &dyn ast::TypeBoundsOwner, | 227 | node: &dyn ast::TypeBoundsOwner, |
221 | type_ref: TypeRef, | 228 | target: Either<TypeRef, LifetimeRef>, |
222 | ) { | 229 | ) { |
223 | for bound in | 230 | for bound in |
224 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | 231 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) |
225 | { | 232 | { |
226 | self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone()); | 233 | self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); |
227 | } | 234 | } |
228 | } | 235 | } |
229 | 236 | ||
@@ -246,19 +253,30 @@ impl GenericParams { | |||
246 | sm.insert(param_id, Either::Right(type_param.clone())); | 253 | sm.insert(param_id, Either::Right(type_param.clone())); |
247 | 254 | ||
248 | let type_ref = TypeRef::Path(name.into()); | 255 | let type_ref = TypeRef::Path(name.into()); |
249 | self.fill_bounds(&lower_ctx, &type_param, type_ref); | 256 | self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); |
257 | } | ||
258 | for lifetime_param in params.lifetime_params() { | ||
259 | let name = lifetime_param | ||
260 | .lifetime_token() | ||
261 | .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok)); | ||
262 | let param = LifetimeParamData { name: name.clone() }; | ||
263 | let _param_id = self.lifetimes.alloc(param); | ||
264 | let lifetime_ref = LifetimeRef::new_name(name); | ||
265 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); | ||
250 | } | 266 | } |
251 | } | 267 | } |
252 | 268 | ||
253 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { | 269 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { |
254 | for pred in where_clause.predicates() { | 270 | for pred in where_clause.predicates() { |
255 | let type_ref = match pred.ty() { | 271 | let target = if let Some(type_ref) = pred.ty() { |
256 | Some(type_ref) => type_ref, | 272 | Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) |
257 | None => continue, | 273 | } else if let Some(lifetime_tok) = pred.lifetime_token() { |
274 | Either::Right(LifetimeRef::from_token(lifetime_tok)) | ||
275 | } else { | ||
276 | continue; | ||
258 | }; | 277 | }; |
259 | let type_ref = TypeRef::from_ast(lower_ctx, type_ref); | ||
260 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | 278 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { |
261 | self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone()); | 279 | self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); |
262 | } | 280 | } |
263 | } | 281 | } |
264 | } | 282 | } |
@@ -267,15 +285,24 @@ impl GenericParams { | |||
267 | &mut self, | 285 | &mut self, |
268 | lower_ctx: &LowerCtx, | 286 | lower_ctx: &LowerCtx, |
269 | bound: ast::TypeBound, | 287 | bound: ast::TypeBound, |
270 | type_ref: TypeRef, | 288 | target: Either<TypeRef, LifetimeRef>, |
271 | ) { | 289 | ) { |
272 | if bound.question_mark_token().is_some() { | 290 | if bound.question_mark_token().is_some() { |
273 | // FIXME: remove this bound | 291 | // FIXME: remove this bound |
274 | return; | 292 | return; |
275 | } | 293 | } |
276 | let bound = TypeBound::from_ast(lower_ctx, bound); | 294 | let bound = TypeBound::from_ast(lower_ctx, bound); |
277 | self.where_predicates | 295 | let predicate = match (target, bound) { |
278 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); | 296 | (Either::Left(type_ref), bound) => WherePredicate::TypeBound { |
297 | target: WherePredicateTypeTarget::TypeRef(type_ref), | ||
298 | bound, | ||
299 | }, | ||
300 | (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { | ||
301 | WherePredicate::Lifetime { target: lifetime, bound } | ||
302 | } | ||
303 | _ => return, | ||
304 | }; | ||
305 | self.where_predicates.push(predicate); | ||
279 | } | 306 | } |
280 | 307 | ||
281 | pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { | 308 | pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { |
@@ -288,8 +315,8 @@ impl GenericParams { | |||
288 | }; | 315 | }; |
289 | let param_id = self.types.alloc(param); | 316 | let param_id = self.types.alloc(param); |
290 | for bound in bounds { | 317 | for bound in bounds { |
291 | self.where_predicates.push(WherePredicate { | 318 | self.where_predicates.push(WherePredicate::TypeBound { |
292 | target: WherePredicateTarget::TypeParam(param_id), | 319 | target: WherePredicateTypeTarget::TypeParam(param_id), |
293 | bound: bound.clone(), | 320 | bound: bound.clone(), |
294 | }); | 321 | }); |
295 | } | 322 | } |