From 622c780a8ca023f09d57b4fa42608410c477128e Mon Sep 17 00:00:00 2001 From: Jonas Schievink <jonasschievink@gmail.com> Date: Wed, 17 Mar 2021 16:29:57 +0100 Subject: 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(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 1a27f7bf2..f9bb0c6da 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -9,7 +9,7 @@ use crate::{ 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 @@ impl FunctionData { let krate = loc.container.module(db).krate; let item_tree = db.item_tree(loc.id.file_id); let func = &item_tree[loc.id.value]; + let is_varargs = func + .params + .clone() + .last() + .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); Arc::new(FunctionData { name: func.name.clone(), - params: func.params.iter().map(|id| item_tree[*id].clone()).collect(), + params: func + .params + .clone() + .filter_map(|id| match &item_tree[id] { + Param::Normal(ty) => 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 7bb22c4c4..c14da95ab 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -134,6 +134,7 @@ impl ItemTree { imports, extern_crates, functions, + params, structs, fields, unions, @@ -157,6 +158,7 @@ impl ItemTree { 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<Import>, extern_crates: Arena<ExternCrate>, functions: Arena<Function>, + params: Arena<Param>, structs: Arena<Struct>, fields: Arena<Field>, unions: Arena<Union>, @@ -334,6 +337,7 @@ pub enum AttrOwner { Variant(Idx<Variant>), Field(Idx<Field>), + Param(Idx<Param>), } macro_rules! from_attrs { @@ -348,7 +352,7 @@ macro_rules! from_attrs { }; } -from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); +from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>), Param(Idx<Param>)); /// Trait implemented by all item nodes in the item tree. pub trait ItemTreeNode: Clone { @@ -484,7 +488,7 @@ macro_rules! impl_index { }; } -impl_index!(fields: Field, variants: Variant); +impl_index!(fields: Field, variants: Variant, params: Param); impl Index<RawVisibilityId> 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<TypeRef>]>, - pub is_varargs: bool, + pub params: IdRange<Param>, pub ret_type: Idx<TypeRef>, pub ast_id: FileAstId<ast::Fn>, } +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Param { + Normal(Idx<TypeRef>), + 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<T> { range: Range<u32>, _p: PhantomData<T>, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 7e91b991d..3f558edd8 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -333,8 +333,8 @@ impl Ctx { 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 @@ impl Ctx { } } }; - 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 @@ impl Ctx { qualifier, is_in_extern_block: false, params, - is_varargs, ret_type, ast_id, }; @@ -682,9 +684,11 @@ impl Ctx { 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 @@ impl Ctx { self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), )) } + fn next_param_idx(&self) -> Idx<Param> { + 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 { -- cgit v1.2.3 From ba0e4c745d60ea1a0e32d1469648394410f6c450 Mon Sep 17 00:00:00 2001 From: Jonas Schievink <jonasschievink@gmail.com> Date: Wed, 17 Mar 2021 18:28:00 +0100 Subject: Apply `#[cfg]`s when computing function signatures --- crates/hir_def/src/data.rs | 15 +++++++++++---- crates/hir_def/src/item_tree.rs | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index f9bb0c6da..e976e419e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -36,18 +36,25 @@ impl FunctionData { pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { let loc = func.lookup(db); let krate = loc.container.module(db).krate; + let crate_graph = db.crate_graph(); + let cfg_options = &crate_graph[krate].cfg_options; let item_tree = db.item_tree(loc.id.file_id); let func = &item_tree[loc.id.value]; - let is_varargs = func + + let enabled_params = func .params .clone() - .last() + .filter(|¶m| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options)); + + // If last cfg-enabled param is a `...` param, it's a varargs function. + let is_varargs = enabled_params + .clone() + .next_back() .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); Arc::new(FunctionData { name: func.name.clone(), - params: func - .params + params: enabled_params .clone() .filter_map(|id| match &item_tree[id] { Param::Normal(ty) => Some(item_tree[*ty].clone()), diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index c14da95ab..90df3d929 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -824,6 +824,12 @@ impl<T> Iterator for IdRange<T> { } } +impl<T> DoubleEndedIterator for IdRange<T> { + fn next_back(&mut self) -> Option<Self::Item> { + self.range.next_back().map(|raw| Idx::from_raw(raw.into())) + } +} + impl<T> fmt::Debug for IdRange<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() -- cgit v1.2.3