From c12f7b610be49901190cde994dfe4f594150dbf9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 17 Jun 2020 12:24:05 +0200 Subject: Lower generics --- crates/ra_hir_def/src/generics.rs | 13 ++++-- crates/ra_hir_def/src/item_tree.rs | 16 +++---- crates/ra_hir_def/src/item_tree/lower.rs | 80 ++++++++++++++++++++++++++------ 3 files changed, 83 insertions(+), 26 deletions(-) (limited to 'crates/ra_hir_def') 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 { } /// Data about the generic parameters of a function, struct, impl, etc. -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Default)] pub struct GenericParams { pub types: Arena, // lifetimes: Arena, @@ -156,7 +156,12 @@ impl GenericParams { (generics, InFile::new(file_id, sm)) } - fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { + pub(crate) fn fill( + &mut self, + lower_ctx: &LowerCtx, + sm: &mut SourceMap, + node: &dyn TypeParamsOwner, + ) { if let Some(params) = node.type_param_list() { self.fill_params(lower_ctx, sm, params) } @@ -165,7 +170,7 @@ impl GenericParams { } } - fn fill_bounds( + pub(crate) fn fill_bounds( &mut self, lower_ctx: &LowerCtx, node: &dyn ast::TypeBoundsOwner, @@ -229,7 +234,7 @@ impl GenericParams { .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); } - fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { + pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { type_ref.walk(&mut |type_ref| { if let TypeRef::ImplTrait(bounds) = type_ref { 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; use crate::{ attr::Attrs, db::DefDatabase, - generics, + generics::GenericParams, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path}, type_ref::{Mutability, TypeBound, TypeRef}, visibility::RawVisibility, @@ -230,7 +230,7 @@ pub struct Function { pub name: Name, pub attrs: Attrs, pub visibility: RawVisibility, - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub has_self_param: bool, pub params: Vec, pub ret_type: TypeRef, @@ -243,7 +243,7 @@ pub struct Struct { pub name: Name, pub attrs: Attrs, pub visibility: RawVisibility, - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub fields: Fields, pub ast_id: FileAstId, pub kind: StructDefKind, @@ -264,7 +264,7 @@ pub struct Union { pub name: Name, pub attrs: Attrs, pub visibility: RawVisibility, - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub fields: Fields, pub ast_id: FileAstId, } @@ -274,7 +274,7 @@ pub struct Enum { pub name: Name, pub attrs: Attrs, pub visibility: RawVisibility, - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub variants: Range>, pub ast_id: FileAstId, } @@ -300,7 +300,7 @@ pub struct Static { pub struct Trait { pub name: Name, pub visibility: RawVisibility, - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub auto: bool, pub items: Vec, pub ast_id: FileAstId, @@ -308,7 +308,7 @@ pub struct Trait { #[derive(Debug, Eq, PartialEq)] pub struct Impl { - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub target_trait: Option, pub target_type: TypeRef, pub is_negative: bool, @@ -320,7 +320,7 @@ pub struct Impl { pub struct TypeAlias { pub name: Name, pub visibility: RawVisibility, - pub generic_params: generics::GenericParams, + pub generic_params: GenericParams, pub type_ref: Option, pub ast_id: FileAstId, } 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 @@ +//! AST -> `ItemTree` lowering code. + use super::*; -use crate::attr::Attrs; +use crate::{ + attr::Attrs, + generics::{GenericParams, TypeParamData, TypeParamProvenance}, +}; use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; +use ra_arena::map::ArenaMap; use ra_syntax::ast::{self, ModuleItemOwner}; use smallvec::SmallVec; use std::sync::Arc; @@ -123,7 +129,7 @@ impl Ctx { let attrs = self.lower_attrs(strukt); let visibility = self.lower_visibility(strukt); let name = strukt.name()?.as_name(); - let generic_params = self.lower_generic_params(strukt); + let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); let fields = self.lower_fields(&strukt.kind()); let ast_id = self.source_ast_id_map.ast_id(strukt); let kind = match strukt.kind() { @@ -191,7 +197,7 @@ impl Ctx { let attrs = self.lower_attrs(union); let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); - let generic_params = self.lower_generic_params(union); + let generic_params = self.lower_generic_params(GenericsOwner::Union, union); let fields = match union.record_field_def_list() { Some(record_field_def_list) => { self.lower_fields(&StructKind::Record(record_field_def_list)) @@ -207,7 +213,7 @@ impl Ctx { let attrs = self.lower_attrs(enum_); let visibility = self.lower_visibility(enum_); let name = enum_.name()?.as_name(); - let generic_params = self.lower_generic_params(enum_); + let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); let variants = match &enum_.variant_list() { Some(variant_list) => self.lower_variants(variant_list), None => self.next_variant_idx()..self.next_variant_idx(), @@ -239,7 +245,6 @@ impl Ctx { let attrs = self.lower_attrs(func); let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); - let generic_params = self.lower_generic_params(func); let mut params = Vec::new(); let mut has_self_param = false; @@ -281,16 +286,17 @@ impl Ctx { }; let ast_id = self.source_ast_id_map.ast_id(func); - let res = Function { + let mut res = Function { name, attrs, visibility, - generic_params, + generic_params: GenericParams::default(), has_self_param, params, ret_type, ast_id, }; + res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); Some(res) } @@ -298,7 +304,7 @@ impl Ctx { let name = type_alias.name()?.as_name(); let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); let visibility = self.lower_visibility(type_alias); - let generic_params = self.lower_generic_params(type_alias); + let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; Some(res) @@ -349,7 +355,7 @@ impl Ctx { fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option { let name = trait_def.name()?.as_name(); let visibility = self.lower_visibility(trait_def); - let generic_params = self.lower_generic_params(trait_def); + let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def); let auto = trait_def.auto_token().is_some(); let items = trait_def.item_list().map(|list| { // FIXME: Does not handle macros @@ -367,7 +373,7 @@ impl Ctx { } fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option { - let generic_params = self.lower_generic_params(impl_def); + let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def); let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); let target_type = self.lower_type_ref(&impl_def.target_type()?); let is_negative = impl_def.excl_token().is_some(); @@ -465,10 +471,43 @@ impl Ctx { fn lower_generic_params( &mut self, - _item: &impl ast::TypeParamsOwner, - ) -> generics::GenericParams { - // TODO - generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() } + owner: GenericsOwner<'_>, + node: &impl ast::TypeParamsOwner, + ) -> GenericParams { + let mut sm = &mut ArenaMap::default(); + let mut generics = GenericParams::default(); + match owner { + GenericsOwner::Function(func) => { + generics.fill(&self.body_ctx, sm, node); + // lower `impl Trait` in arguments + for param in &func.params { + generics.fill_implicit_impl_trait_args(param); + } + } + GenericsOwner::Struct + | GenericsOwner::Enum + | GenericsOwner::Union + | GenericsOwner::TypeAlias => { + generics.fill(&self.body_ctx, sm, node); + } + GenericsOwner::Trait(trait_def) => { + // traits get the Self type as an implicit first type parameter + let self_param_id = generics.types.alloc(TypeParamData { + name: Some(name![Self]), + default: None, + provenance: TypeParamProvenance::TraitSelf, + }); + sm.insert(self_param_id, Either::Left(trait_def.clone())); + // add super traits as bounds on Self + // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar + let self_param = TypeRef::Path(name![Self].into()); + generics.fill_bounds(&self.body_ctx, trait_def, self_param); + + generics.fill(&self.body_ctx, &mut sm, node); + } + GenericsOwner::Impl => {} + } + generics } fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { @@ -503,3 +542,16 @@ fn desugar_future_path(orig: TypeRef) -> Path { Path::from_known_path(path, generic_args) } + +enum GenericsOwner<'a> { + /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument + /// position. + Function(&'a Function), + Struct, + Enum, + Union, + /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter. + Trait(&'a ast::TraitDef), + TypeAlias, + Impl, +} -- cgit v1.2.3