From 622c780a8ca023f09d57b4fa42608410c477128e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 17 Mar 2021 16:29:57 +0100 Subject: [PATCH] ItemTree: lower attributes on fn parameters --- crates/hir_def/src/data.rs | 18 ++++++++++-- crates/hir_def/src/item_tree.rs | 18 +++++++++--- crates/hir_def/src/item_tree/lower.rs | 41 ++++++++++++++++----------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 1a27f7bf21b..f9bb0c6da47 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -9,7 +9,7 @@ attr::Attrs, body::Expander, db::DefDatabase, - item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem}, + item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, type_ref::{TypeBound, TypeRef}, visibility::RawVisibility, AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, @@ -38,17 +38,29 @@ pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc Some(item_tree[*ty].clone()), + Param::Varargs => None, + }) + .collect(), ret_type: item_tree[func.ret_type].clone(), attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), has_self_param: func.has_self_param, has_body: func.has_body, qualifier: func.qualifier.clone(), is_in_extern_block: func.is_in_extern_block, - is_varargs: func.is_varargs, + is_varargs, visibility: item_tree[func.visibility].clone(), }) } diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 7bb22c4c49f..c14da95ab56 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -134,6 +134,7 @@ fn shrink_to_fit(&mut self) { imports, extern_crates, functions, + params, structs, fields, unions, @@ -157,6 +158,7 @@ fn shrink_to_fit(&mut self) { imports.shrink_to_fit(); extern_crates.shrink_to_fit(); functions.shrink_to_fit(); + params.shrink_to_fit(); structs.shrink_to_fit(); fields.shrink_to_fit(); unions.shrink_to_fit(); @@ -303,6 +305,7 @@ struct ItemTreeData { imports: Arena, extern_crates: Arena, functions: Arena, + params: Arena, structs: Arena, fields: Arena, unions: Arena, @@ -334,6 +337,7 @@ pub enum AttrOwner { Variant(Idx), Field(Idx), + Param(Idx), } macro_rules! from_attrs { @@ -348,7 +352,7 @@ fn from(t: $t) -> AttrOwner { }; } -from_attrs!(ModItem(ModItem), Variant(Idx), Field(Idx)); +from_attrs!(ModItem(ModItem), Variant(Idx), Field(Idx), Param(Idx)); /// Trait implemented by all item nodes in the item tree. pub trait ItemTreeNode: Clone { @@ -484,7 +488,7 @@ fn index(&self, index: Idx<$t>) -> &Self::Output { }; } -impl_index!(fields: Field, variants: Variant); +impl_index!(fields: Field, variants: Variant, params: Param); impl Index for ItemTree { type Output = RawVisibility; @@ -560,12 +564,17 @@ pub struct Function { /// Whether the function is located in an `extern` block (*not* whether it is an /// `extern "abi" fn`). pub is_in_extern_block: bool, - pub params: Box<[Idx]>, - pub is_varargs: bool, + pub params: IdRange, pub ret_type: Idx, pub ast_id: FileAstId, } +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Param { + Normal(Idx), + Varargs, +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct FunctionQualifier { pub is_default: bool, @@ -796,6 +805,7 @@ pub struct Variant { pub fields: Fields, } +/// A range of densely allocated ItemTree IDs. pub struct IdRange { range: Range, _p: PhantomData, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 7e91b991d2c..3f558edd816 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -333,8 +333,8 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option> let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); - let mut params = Vec::new(); let mut has_self_param = false; + let start_param = self.next_param_idx(); if let Some(param_list) = func.param_list() { if let Some(self_param) = param_list.self_param() { let self_type = match self_param.ty() { @@ -356,22 +356,25 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option> } } }; - params.push(self_type); + let ty = self.data().type_refs.intern(self_type); + let idx = self.data().params.alloc(Param::Normal(ty)); + self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); has_self_param = true; } for param in param_list.params() { - let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); - params.push(type_ref); - } - } - let params = params.into_iter().map(|param| self.data().type_refs.intern(param)).collect(); - - let mut is_varargs = false; - if let Some(params) = func.param_list() { - if let Some(last) = params.params().last() { - is_varargs = last.dotdotdot_token().is_some(); + let idx = match param.dotdotdot_token() { + Some(_) => self.data().params.alloc(Param::Varargs), + None => { + let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); + let ty = self.data().type_refs.intern(type_ref); + self.data().params.alloc(Param::Normal(ty)) + } + }; + self.add_attrs(idx.into(), RawAttrs::new(¶m, &self.hygiene)); } } + let end_param = self.next_param_idx(); + let params = IdRange::new(start_param..end_param); let ret_type = match func.ret_type().and_then(|rt| rt.ty()) { Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), @@ -419,7 +422,6 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option> qualifier, is_in_extern_block: false, params, - is_varargs, ret_type, ast_id, }; @@ -682,9 +684,11 @@ fn lower_generic_params( GenericsOwner::Function(func) => { generics.fill(&self.body_ctx, sm, node); // lower `impl Trait` in arguments - for param in &*func.params { - let param = self.data().type_refs.lookup(*param); - generics.fill_implicit_impl_trait_args(param); + for id in func.params.clone() { + if let Param::Normal(ty) = self.data().params[id] { + let ty = self.data().type_refs.lookup(ty); + generics.fill_implicit_impl_trait_args(ty); + } } } GenericsOwner::Struct @@ -769,6 +773,11 @@ fn next_variant_idx(&self) -> Idx { self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), )) } + fn next_param_idx(&self) -> Idx { + Idx::from_raw(RawIdx::from( + self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32), + )) + } } fn desugar_future_path(orig: TypeRef) -> Path {