diff options
Diffstat (limited to 'crates/ra_hir_def/src/item_tree/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 80 |
1 files changed, 66 insertions, 14 deletions
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 | } | ||