From 622c780a8ca023f09d57b4fa42608410c477128e Mon Sep 17 00:00:00 2001 From: Jonas Schievink 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/src') 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, 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 @@ macro_rules! from_attrs { }; } -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 @@ macro_rules! impl_index { }; } -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 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 { + 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 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/src') 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 { 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 Iterator for IdRange { } } +impl DoubleEndedIterator for IdRange { + fn next_back(&mut self) -> Option { + self.range.next_back().map(|raw| Idx::from_raw(raw.into())) + } +} + impl fmt::Debug for IdRange { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple(&format!("IdRange::<{}>", type_name::())).field(&self.range).finish() -- cgit v1.2.3