diff options
author | Jonas Schievink <[email protected]> | 2020-06-17 11:24:05 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2020-06-24 15:53:16 +0100 |
commit | c12f7b610be49901190cde994dfe4f594150dbf9 (patch) | |
tree | dcbcf0f72f8fb23601f415fb390561dff94ffb9a /crates/ra_hir_def | |
parent | 864b650f92388f4e82d130713b2de9afe637102f (diff) |
Lower generics
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 80 |
3 files changed, 83 insertions, 26 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 09a5241f7..ed4f60c66 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -42,7 +42,7 @@ pub enum TypeParamProvenance { | |||
42 | } | 42 | } |
43 | 43 | ||
44 | /// Data about the generic parameters of a function, struct, impl, etc. | 44 | /// Data about the generic parameters of a function, struct, impl, etc. |
45 | #[derive(Clone, PartialEq, Eq, Debug)] | 45 | #[derive(Clone, PartialEq, Eq, Debug, Default)] |
46 | pub struct GenericParams { | 46 | pub struct GenericParams { |
47 | pub types: Arena<TypeParamData>, | 47 | pub types: Arena<TypeParamData>, |
48 | // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>, | 48 | // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>, |
@@ -156,7 +156,12 @@ impl GenericParams { | |||
156 | (generics, InFile::new(file_id, sm)) | 156 | (generics, InFile::new(file_id, sm)) |
157 | } | 157 | } |
158 | 158 | ||
159 | fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { | 159 | pub(crate) fn fill( |
160 | &mut self, | ||
161 | lower_ctx: &LowerCtx, | ||
162 | sm: &mut SourceMap, | ||
163 | node: &dyn TypeParamsOwner, | ||
164 | ) { | ||
160 | if let Some(params) = node.type_param_list() { | 165 | if let Some(params) = node.type_param_list() { |
161 | self.fill_params(lower_ctx, sm, params) | 166 | self.fill_params(lower_ctx, sm, params) |
162 | } | 167 | } |
@@ -165,7 +170,7 @@ impl GenericParams { | |||
165 | } | 170 | } |
166 | } | 171 | } |
167 | 172 | ||
168 | fn fill_bounds( | 173 | pub(crate) fn fill_bounds( |
169 | &mut self, | 174 | &mut self, |
170 | lower_ctx: &LowerCtx, | 175 | lower_ctx: &LowerCtx, |
171 | node: &dyn ast::TypeBoundsOwner, | 176 | node: &dyn ast::TypeBoundsOwner, |
@@ -229,7 +234,7 @@ impl GenericParams { | |||
229 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); | 234 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); |
230 | } | 235 | } |
231 | 236 | ||
232 | fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { | 237 | pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { |
233 | type_ref.walk(&mut |type_ref| { | 238 | type_ref.walk(&mut |type_ref| { |
234 | if let TypeRef::ImplTrait(bounds) = type_ref { | 239 | if let TypeRef::ImplTrait(bounds) = type_ref { |
235 | let param = TypeParamData { | 240 | let param = TypeParamData { |
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index 9656f845e..c3990c2eb 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -26,7 +26,7 @@ use test_utils::mark; | |||
26 | use crate::{ | 26 | use crate::{ |
27 | attr::Attrs, | 27 | attr::Attrs, |
28 | db::DefDatabase, | 28 | db::DefDatabase, |
29 | generics, | 29 | generics::GenericParams, |
30 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path}, | 30 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path}, |
31 | type_ref::{Mutability, TypeBound, TypeRef}, | 31 | type_ref::{Mutability, TypeBound, TypeRef}, |
32 | visibility::RawVisibility, | 32 | visibility::RawVisibility, |
@@ -230,7 +230,7 @@ pub struct Function { | |||
230 | pub name: Name, | 230 | pub name: Name, |
231 | pub attrs: Attrs, | 231 | pub attrs: Attrs, |
232 | pub visibility: RawVisibility, | 232 | pub visibility: RawVisibility, |
233 | pub generic_params: generics::GenericParams, | 233 | pub generic_params: GenericParams, |
234 | pub has_self_param: bool, | 234 | pub has_self_param: bool, |
235 | pub params: Vec<TypeRef>, | 235 | pub params: Vec<TypeRef>, |
236 | pub ret_type: TypeRef, | 236 | pub ret_type: TypeRef, |
@@ -243,7 +243,7 @@ pub struct Struct { | |||
243 | pub name: Name, | 243 | pub name: Name, |
244 | pub attrs: Attrs, | 244 | pub attrs: Attrs, |
245 | pub visibility: RawVisibility, | 245 | pub visibility: RawVisibility, |
246 | pub generic_params: generics::GenericParams, | 246 | pub generic_params: GenericParams, |
247 | pub fields: Fields, | 247 | pub fields: Fields, |
248 | pub ast_id: FileAstId<ast::StructDef>, | 248 | pub ast_id: FileAstId<ast::StructDef>, |
249 | pub kind: StructDefKind, | 249 | pub kind: StructDefKind, |
@@ -264,7 +264,7 @@ pub struct Union { | |||
264 | pub name: Name, | 264 | pub name: Name, |
265 | pub attrs: Attrs, | 265 | pub attrs: Attrs, |
266 | pub visibility: RawVisibility, | 266 | pub visibility: RawVisibility, |
267 | pub generic_params: generics::GenericParams, | 267 | pub generic_params: GenericParams, |
268 | pub fields: Fields, | 268 | pub fields: Fields, |
269 | pub ast_id: FileAstId<ast::UnionDef>, | 269 | pub ast_id: FileAstId<ast::UnionDef>, |
270 | } | 270 | } |
@@ -274,7 +274,7 @@ pub struct Enum { | |||
274 | pub name: Name, | 274 | pub name: Name, |
275 | pub attrs: Attrs, | 275 | pub attrs: Attrs, |
276 | pub visibility: RawVisibility, | 276 | pub visibility: RawVisibility, |
277 | pub generic_params: generics::GenericParams, | 277 | pub generic_params: GenericParams, |
278 | pub variants: Range<Idx<Variant>>, | 278 | pub variants: Range<Idx<Variant>>, |
279 | pub ast_id: FileAstId<ast::EnumDef>, | 279 | pub ast_id: FileAstId<ast::EnumDef>, |
280 | } | 280 | } |
@@ -300,7 +300,7 @@ pub struct Static { | |||
300 | pub struct Trait { | 300 | pub struct Trait { |
301 | pub name: Name, | 301 | pub name: Name, |
302 | pub visibility: RawVisibility, | 302 | pub visibility: RawVisibility, |
303 | pub generic_params: generics::GenericParams, | 303 | pub generic_params: GenericParams, |
304 | pub auto: bool, | 304 | pub auto: bool, |
305 | pub items: Vec<AssocItem>, | 305 | pub items: Vec<AssocItem>, |
306 | pub ast_id: FileAstId<ast::TraitDef>, | 306 | pub ast_id: FileAstId<ast::TraitDef>, |
@@ -308,7 +308,7 @@ pub struct Trait { | |||
308 | 308 | ||
309 | #[derive(Debug, Eq, PartialEq)] | 309 | #[derive(Debug, Eq, PartialEq)] |
310 | pub struct Impl { | 310 | pub struct Impl { |
311 | pub generic_params: generics::GenericParams, | 311 | pub generic_params: GenericParams, |
312 | pub target_trait: Option<TypeRef>, | 312 | pub target_trait: Option<TypeRef>, |
313 | pub target_type: TypeRef, | 313 | pub target_type: TypeRef, |
314 | pub is_negative: bool, | 314 | pub is_negative: bool, |
@@ -320,7 +320,7 @@ pub struct Impl { | |||
320 | pub struct TypeAlias { | 320 | pub struct TypeAlias { |
321 | pub name: Name, | 321 | pub name: Name, |
322 | pub visibility: RawVisibility, | 322 | pub visibility: RawVisibility, |
323 | pub generic_params: generics::GenericParams, | 323 | pub generic_params: GenericParams, |
324 | pub type_ref: Option<TypeRef>, | 324 | pub type_ref: Option<TypeRef>, |
325 | pub ast_id: FileAstId<ast::TypeAliasDef>, | 325 | pub ast_id: FileAstId<ast::TypeAliasDef>, |
326 | } | 326 | } |
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 0c9454848..737a69c30 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -1,6 +1,12 @@ | |||
1 | //! AST -> `ItemTree` lowering code. | ||
2 | |||
1 | use super::*; | 3 | use super::*; |
2 | use crate::attr::Attrs; | 4 | use crate::{ |
5 | attr::Attrs, | ||
6 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | ||
7 | }; | ||
3 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; | 8 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; |
9 | use ra_arena::map::ArenaMap; | ||
4 | use ra_syntax::ast::{self, ModuleItemOwner}; | 10 | use ra_syntax::ast::{self, ModuleItemOwner}; |
5 | use smallvec::SmallVec; | 11 | use smallvec::SmallVec; |
6 | use std::sync::Arc; | 12 | use std::sync::Arc; |
@@ -123,7 +129,7 @@ impl Ctx { | |||
123 | let attrs = self.lower_attrs(strukt); | 129 | let attrs = self.lower_attrs(strukt); |
124 | let visibility = self.lower_visibility(strukt); | 130 | let visibility = self.lower_visibility(strukt); |
125 | let name = strukt.name()?.as_name(); | 131 | let name = strukt.name()?.as_name(); |
126 | let generic_params = self.lower_generic_params(strukt); | 132 | let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); |
127 | let fields = self.lower_fields(&strukt.kind()); | 133 | let fields = self.lower_fields(&strukt.kind()); |
128 | let ast_id = self.source_ast_id_map.ast_id(strukt); | 134 | let ast_id = self.source_ast_id_map.ast_id(strukt); |
129 | let kind = match strukt.kind() { | 135 | let kind = match strukt.kind() { |
@@ -191,7 +197,7 @@ impl Ctx { | |||
191 | let attrs = self.lower_attrs(union); | 197 | let attrs = self.lower_attrs(union); |
192 | let visibility = self.lower_visibility(union); | 198 | let visibility = self.lower_visibility(union); |
193 | let name = union.name()?.as_name(); | 199 | let name = union.name()?.as_name(); |
194 | let generic_params = self.lower_generic_params(union); | 200 | let generic_params = self.lower_generic_params(GenericsOwner::Union, union); |
195 | let fields = match union.record_field_def_list() { | 201 | let fields = match union.record_field_def_list() { |
196 | Some(record_field_def_list) => { | 202 | Some(record_field_def_list) => { |
197 | self.lower_fields(&StructKind::Record(record_field_def_list)) | 203 | self.lower_fields(&StructKind::Record(record_field_def_list)) |
@@ -207,7 +213,7 @@ impl Ctx { | |||
207 | let attrs = self.lower_attrs(enum_); | 213 | let attrs = self.lower_attrs(enum_); |
208 | let visibility = self.lower_visibility(enum_); | 214 | let visibility = self.lower_visibility(enum_); |
209 | let name = enum_.name()?.as_name(); | 215 | let name = enum_.name()?.as_name(); |
210 | let generic_params = self.lower_generic_params(enum_); | 216 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); |
211 | let variants = match &enum_.variant_list() { | 217 | let variants = match &enum_.variant_list() { |
212 | Some(variant_list) => self.lower_variants(variant_list), | 218 | Some(variant_list) => self.lower_variants(variant_list), |
213 | None => self.next_variant_idx()..self.next_variant_idx(), | 219 | None => self.next_variant_idx()..self.next_variant_idx(), |
@@ -239,7 +245,6 @@ impl Ctx { | |||
239 | let attrs = self.lower_attrs(func); | 245 | let attrs = self.lower_attrs(func); |
240 | let visibility = self.lower_visibility(func); | 246 | let visibility = self.lower_visibility(func); |
241 | let name = func.name()?.as_name(); | 247 | let name = func.name()?.as_name(); |
242 | let generic_params = self.lower_generic_params(func); | ||
243 | 248 | ||
244 | let mut params = Vec::new(); | 249 | let mut params = Vec::new(); |
245 | let mut has_self_param = false; | 250 | let mut has_self_param = false; |
@@ -281,16 +286,17 @@ impl Ctx { | |||
281 | }; | 286 | }; |
282 | 287 | ||
283 | let ast_id = self.source_ast_id_map.ast_id(func); | 288 | let ast_id = self.source_ast_id_map.ast_id(func); |
284 | let res = Function { | 289 | let mut res = Function { |
285 | name, | 290 | name, |
286 | attrs, | 291 | attrs, |
287 | visibility, | 292 | visibility, |
288 | generic_params, | 293 | generic_params: GenericParams::default(), |
289 | has_self_param, | 294 | has_self_param, |
290 | params, | 295 | params, |
291 | ret_type, | 296 | ret_type, |
292 | ast_id, | 297 | ast_id, |
293 | }; | 298 | }; |
299 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); | ||
294 | Some(res) | 300 | Some(res) |
295 | } | 301 | } |
296 | 302 | ||
@@ -298,7 +304,7 @@ impl Ctx { | |||
298 | let name = type_alias.name()?.as_name(); | 304 | let name = type_alias.name()?.as_name(); |
299 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); | 305 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); |
300 | let visibility = self.lower_visibility(type_alias); | 306 | let visibility = self.lower_visibility(type_alias); |
301 | let generic_params = self.lower_generic_params(type_alias); | 307 | let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias); |
302 | let ast_id = self.source_ast_id_map.ast_id(type_alias); | 308 | let ast_id = self.source_ast_id_map.ast_id(type_alias); |
303 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; | 309 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; |
304 | Some(res) | 310 | Some(res) |
@@ -349,7 +355,7 @@ impl Ctx { | |||
349 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { | 355 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { |
350 | let name = trait_def.name()?.as_name(); | 356 | let name = trait_def.name()?.as_name(); |
351 | let visibility = self.lower_visibility(trait_def); | 357 | let visibility = self.lower_visibility(trait_def); |
352 | let generic_params = self.lower_generic_params(trait_def); | 358 | let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def); |
353 | let auto = trait_def.auto_token().is_some(); | 359 | let auto = trait_def.auto_token().is_some(); |
354 | let items = trait_def.item_list().map(|list| { | 360 | let items = trait_def.item_list().map(|list| { |
355 | // FIXME: Does not handle macros | 361 | // FIXME: Does not handle macros |
@@ -367,7 +373,7 @@ impl Ctx { | |||
367 | } | 373 | } |
368 | 374 | ||
369 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { | 375 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { |
370 | let generic_params = self.lower_generic_params(impl_def); | 376 | let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def); |
371 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); | 377 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); |
372 | let target_type = self.lower_type_ref(&impl_def.target_type()?); | 378 | let target_type = self.lower_type_ref(&impl_def.target_type()?); |
373 | let is_negative = impl_def.excl_token().is_some(); | 379 | let is_negative = impl_def.excl_token().is_some(); |
@@ -465,10 +471,43 @@ impl Ctx { | |||
465 | 471 | ||
466 | fn lower_generic_params( | 472 | fn lower_generic_params( |
467 | &mut self, | 473 | &mut self, |
468 | _item: &impl ast::TypeParamsOwner, | 474 | owner: GenericsOwner<'_>, |
469 | ) -> generics::GenericParams { | 475 | node: &impl ast::TypeParamsOwner, |
470 | // TODO | 476 | ) -> GenericParams { |
471 | generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() } | 477 | let mut sm = &mut ArenaMap::default(); |
478 | let mut generics = GenericParams::default(); | ||
479 | match owner { | ||
480 | GenericsOwner::Function(func) => { | ||
481 | generics.fill(&self.body_ctx, sm, node); | ||
482 | // lower `impl Trait` in arguments | ||
483 | for param in &func.params { | ||
484 | generics.fill_implicit_impl_trait_args(param); | ||
485 | } | ||
486 | } | ||
487 | GenericsOwner::Struct | ||
488 | | GenericsOwner::Enum | ||
489 | | GenericsOwner::Union | ||
490 | | GenericsOwner::TypeAlias => { | ||
491 | generics.fill(&self.body_ctx, sm, node); | ||
492 | } | ||
493 | GenericsOwner::Trait(trait_def) => { | ||
494 | // traits get the Self type as an implicit first type parameter | ||
495 | let self_param_id = generics.types.alloc(TypeParamData { | ||
496 | name: Some(name![Self]), | ||
497 | default: None, | ||
498 | provenance: TypeParamProvenance::TraitSelf, | ||
499 | }); | ||
500 | sm.insert(self_param_id, Either::Left(trait_def.clone())); | ||
501 | // add super traits as bounds on Self | ||
502 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | ||
503 | let self_param = TypeRef::Path(name![Self].into()); | ||
504 | generics.fill_bounds(&self.body_ctx, trait_def, self_param); | ||
505 | |||
506 | generics.fill(&self.body_ctx, &mut sm, node); | ||
507 | } | ||
508 | GenericsOwner::Impl => {} | ||
509 | } | ||
510 | generics | ||
472 | } | 511 | } |
473 | 512 | ||
474 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | 513 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { |
@@ -503,3 +542,16 @@ fn desugar_future_path(orig: TypeRef) -> Path { | |||
503 | 542 | ||
504 | Path::from_known_path(path, generic_args) | 543 | Path::from_known_path(path, generic_args) |
505 | } | 544 | } |
545 | |||
546 | enum GenericsOwner<'a> { | ||
547 | /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument | ||
548 | /// position. | ||
549 | Function(&'a Function), | ||
550 | Struct, | ||
551 | Enum, | ||
552 | Union, | ||
553 | /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter. | ||
554 | Trait(&'a ast::TraitDef), | ||
555 | TypeAlias, | ||
556 | Impl, | ||
557 | } | ||