diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-17 17:36:13 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-17 17:36:13 +0000 |
commit | 4fa56e3ab10ce3214cae2fdef1973eef406180ce (patch) | |
tree | daca310d9e603096737b5da12cdd573fdaf1d530 /crates/hir_def/src | |
parent | 0a6471384529bd8861c628756695c52be4c6837f (diff) | |
parent | 9436436d20db4d7b13809844ef3e12563dc6be65 (diff) |
Merge #8068
8068: Correctly handle `#[cfg]` on function parameters r=jonas-schievink a=jonas-schievink
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/5649
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/data.rs | 25 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 24 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 41 |
3 files changed, 67 insertions, 23 deletions
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 1a27f7bf2..e976e419e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -9,7 +9,7 @@ use crate::{ | |||
9 | attr::Attrs, | 9 | attr::Attrs, |
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem}, | 12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, |
13 | type_ref::{TypeBound, TypeRef}, | 13 | type_ref::{TypeBound, TypeRef}, |
14 | visibility::RawVisibility, | 14 | visibility::RawVisibility, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -36,19 +36,38 @@ impl FunctionData { | |||
36 | pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { | 36 | pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { |
37 | let loc = func.lookup(db); | 37 | let loc = func.lookup(db); |
38 | let krate = loc.container.module(db).krate; | 38 | let krate = loc.container.module(db).krate; |
39 | let crate_graph = db.crate_graph(); | ||
40 | let cfg_options = &crate_graph[krate].cfg_options; | ||
39 | let item_tree = db.item_tree(loc.id.file_id); | 41 | let item_tree = db.item_tree(loc.id.file_id); |
40 | let func = &item_tree[loc.id.value]; | 42 | let func = &item_tree[loc.id.value]; |
41 | 43 | ||
44 | let enabled_params = func | ||
45 | .params | ||
46 | .clone() | ||
47 | .filter(|¶m| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options)); | ||
48 | |||
49 | // If last cfg-enabled param is a `...` param, it's a varargs function. | ||
50 | let is_varargs = enabled_params | ||
51 | .clone() | ||
52 | .next_back() | ||
53 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); | ||
54 | |||
42 | Arc::new(FunctionData { | 55 | Arc::new(FunctionData { |
43 | name: func.name.clone(), | 56 | name: func.name.clone(), |
44 | params: func.params.iter().map(|id| item_tree[*id].clone()).collect(), | 57 | params: enabled_params |
58 | .clone() | ||
59 | .filter_map(|id| match &item_tree[id] { | ||
60 | Param::Normal(ty) => Some(item_tree[*ty].clone()), | ||
61 | Param::Varargs => None, | ||
62 | }) | ||
63 | .collect(), | ||
45 | ret_type: item_tree[func.ret_type].clone(), | 64 | ret_type: item_tree[func.ret_type].clone(), |
46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 65 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
47 | has_self_param: func.has_self_param, | 66 | has_self_param: func.has_self_param, |
48 | has_body: func.has_body, | 67 | has_body: func.has_body, |
49 | qualifier: func.qualifier.clone(), | 68 | qualifier: func.qualifier.clone(), |
50 | is_in_extern_block: func.is_in_extern_block, | 69 | is_in_extern_block: func.is_in_extern_block, |
51 | is_varargs: func.is_varargs, | 70 | is_varargs, |
52 | visibility: item_tree[func.visibility].clone(), | 71 | visibility: item_tree[func.visibility].clone(), |
53 | }) | 72 | }) |
54 | } | 73 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 7bb22c4c4..90df3d929 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -134,6 +134,7 @@ impl ItemTree { | |||
134 | imports, | 134 | imports, |
135 | extern_crates, | 135 | extern_crates, |
136 | functions, | 136 | functions, |
137 | params, | ||
137 | structs, | 138 | structs, |
138 | fields, | 139 | fields, |
139 | unions, | 140 | unions, |
@@ -157,6 +158,7 @@ impl ItemTree { | |||
157 | imports.shrink_to_fit(); | 158 | imports.shrink_to_fit(); |
158 | extern_crates.shrink_to_fit(); | 159 | extern_crates.shrink_to_fit(); |
159 | functions.shrink_to_fit(); | 160 | functions.shrink_to_fit(); |
161 | params.shrink_to_fit(); | ||
160 | structs.shrink_to_fit(); | 162 | structs.shrink_to_fit(); |
161 | fields.shrink_to_fit(); | 163 | fields.shrink_to_fit(); |
162 | unions.shrink_to_fit(); | 164 | unions.shrink_to_fit(); |
@@ -303,6 +305,7 @@ struct ItemTreeData { | |||
303 | imports: Arena<Import>, | 305 | imports: Arena<Import>, |
304 | extern_crates: Arena<ExternCrate>, | 306 | extern_crates: Arena<ExternCrate>, |
305 | functions: Arena<Function>, | 307 | functions: Arena<Function>, |
308 | params: Arena<Param>, | ||
306 | structs: Arena<Struct>, | 309 | structs: Arena<Struct>, |
307 | fields: Arena<Field>, | 310 | fields: Arena<Field>, |
308 | unions: Arena<Union>, | 311 | unions: Arena<Union>, |
@@ -334,6 +337,7 @@ pub enum AttrOwner { | |||
334 | 337 | ||
335 | Variant(Idx<Variant>), | 338 | Variant(Idx<Variant>), |
336 | Field(Idx<Field>), | 339 | Field(Idx<Field>), |
340 | Param(Idx<Param>), | ||
337 | } | 341 | } |
338 | 342 | ||
339 | macro_rules! from_attrs { | 343 | macro_rules! from_attrs { |
@@ -348,7 +352,7 @@ macro_rules! from_attrs { | |||
348 | }; | 352 | }; |
349 | } | 353 | } |
350 | 354 | ||
351 | from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); | 355 | from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>), Param(Idx<Param>)); |
352 | 356 | ||
353 | /// Trait implemented by all item nodes in the item tree. | 357 | /// Trait implemented by all item nodes in the item tree. |
354 | pub trait ItemTreeNode: Clone { | 358 | pub trait ItemTreeNode: Clone { |
@@ -484,7 +488,7 @@ macro_rules! impl_index { | |||
484 | }; | 488 | }; |
485 | } | 489 | } |
486 | 490 | ||
487 | impl_index!(fields: Field, variants: Variant); | 491 | impl_index!(fields: Field, variants: Variant, params: Param); |
488 | 492 | ||
489 | impl Index<RawVisibilityId> for ItemTree { | 493 | impl Index<RawVisibilityId> for ItemTree { |
490 | type Output = RawVisibility; | 494 | type Output = RawVisibility; |
@@ -560,12 +564,17 @@ pub struct Function { | |||
560 | /// Whether the function is located in an `extern` block (*not* whether it is an | 564 | /// Whether the function is located in an `extern` block (*not* whether it is an |
561 | /// `extern "abi" fn`). | 565 | /// `extern "abi" fn`). |
562 | pub is_in_extern_block: bool, | 566 | pub is_in_extern_block: bool, |
563 | pub params: Box<[Idx<TypeRef>]>, | 567 | pub params: IdRange<Param>, |
564 | pub is_varargs: bool, | ||
565 | pub ret_type: Idx<TypeRef>, | 568 | pub ret_type: Idx<TypeRef>, |
566 | pub ast_id: FileAstId<ast::Fn>, | 569 | pub ast_id: FileAstId<ast::Fn>, |
567 | } | 570 | } |
568 | 571 | ||
572 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
573 | pub enum Param { | ||
574 | Normal(Idx<TypeRef>), | ||
575 | Varargs, | ||
576 | } | ||
577 | |||
569 | #[derive(Debug, Clone, PartialEq, Eq)] | 578 | #[derive(Debug, Clone, PartialEq, Eq)] |
570 | pub struct FunctionQualifier { | 579 | pub struct FunctionQualifier { |
571 | pub is_default: bool, | 580 | pub is_default: bool, |
@@ -796,6 +805,7 @@ pub struct Variant { | |||
796 | pub fields: Fields, | 805 | pub fields: Fields, |
797 | } | 806 | } |
798 | 807 | ||
808 | /// A range of densely allocated ItemTree IDs. | ||
799 | pub struct IdRange<T> { | 809 | pub struct IdRange<T> { |
800 | range: Range<u32>, | 810 | range: Range<u32>, |
801 | _p: PhantomData<T>, | 811 | _p: PhantomData<T>, |
@@ -814,6 +824,12 @@ impl<T> Iterator for IdRange<T> { | |||
814 | } | 824 | } |
815 | } | 825 | } |
816 | 826 | ||
827 | impl<T> DoubleEndedIterator for IdRange<T> { | ||
828 | fn next_back(&mut self) -> Option<Self::Item> { | ||
829 | self.range.next_back().map(|raw| Idx::from_raw(raw.into())) | ||
830 | } | ||
831 | } | ||
832 | |||
817 | impl<T> fmt::Debug for IdRange<T> { | 833 | impl<T> fmt::Debug for IdRange<T> { |
818 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 834 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
819 | f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() | 835 | f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() |
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 { | |||
333 | let visibility = self.lower_visibility(func); | 333 | let visibility = self.lower_visibility(func); |
334 | let name = func.name()?.as_name(); | 334 | let name = func.name()?.as_name(); |
335 | 335 | ||
336 | let mut params = Vec::new(); | ||
337 | let mut has_self_param = false; | 336 | let mut has_self_param = false; |
337 | let start_param = self.next_param_idx(); | ||
338 | if let Some(param_list) = func.param_list() { | 338 | if let Some(param_list) = func.param_list() { |
339 | if let Some(self_param) = param_list.self_param() { | 339 | if let Some(self_param) = param_list.self_param() { |
340 | let self_type = match self_param.ty() { | 340 | let self_type = match self_param.ty() { |
@@ -356,22 +356,25 @@ impl Ctx { | |||
356 | } | 356 | } |
357 | } | 357 | } |
358 | }; | 358 | }; |
359 | params.push(self_type); | 359 | let ty = self.data().type_refs.intern(self_type); |
360 | let idx = self.data().params.alloc(Param::Normal(ty)); | ||
361 | self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); | ||
360 | has_self_param = true; | 362 | has_self_param = true; |
361 | } | 363 | } |
362 | for param in param_list.params() { | 364 | for param in param_list.params() { |
363 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); | 365 | let idx = match param.dotdotdot_token() { |
364 | params.push(type_ref); | 366 | Some(_) => self.data().params.alloc(Param::Varargs), |
365 | } | 367 | None => { |
366 | } | 368 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); |
367 | let params = params.into_iter().map(|param| self.data().type_refs.intern(param)).collect(); | 369 | let ty = self.data().type_refs.intern(type_ref); |
368 | 370 | self.data().params.alloc(Param::Normal(ty)) | |
369 | let mut is_varargs = false; | 371 | } |
370 | if let Some(params) = func.param_list() { | 372 | }; |
371 | if let Some(last) = params.params().last() { | 373 | self.add_attrs(idx.into(), RawAttrs::new(¶m, &self.hygiene)); |
372 | is_varargs = last.dotdotdot_token().is_some(); | ||
373 | } | 374 | } |
374 | } | 375 | } |
376 | let end_param = self.next_param_idx(); | ||
377 | let params = IdRange::new(start_param..end_param); | ||
375 | 378 | ||
376 | let ret_type = match func.ret_type().and_then(|rt| rt.ty()) { | 379 | let ret_type = match func.ret_type().and_then(|rt| rt.ty()) { |
377 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), | 380 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), |
@@ -419,7 +422,6 @@ impl Ctx { | |||
419 | qualifier, | 422 | qualifier, |
420 | is_in_extern_block: false, | 423 | is_in_extern_block: false, |
421 | params, | 424 | params, |
422 | is_varargs, | ||
423 | ret_type, | 425 | ret_type, |
424 | ast_id, | 426 | ast_id, |
425 | }; | 427 | }; |
@@ -682,9 +684,11 @@ impl Ctx { | |||
682 | GenericsOwner::Function(func) => { | 684 | GenericsOwner::Function(func) => { |
683 | generics.fill(&self.body_ctx, sm, node); | 685 | generics.fill(&self.body_ctx, sm, node); |
684 | // lower `impl Trait` in arguments | 686 | // lower `impl Trait` in arguments |
685 | for param in &*func.params { | 687 | for id in func.params.clone() { |
686 | let param = self.data().type_refs.lookup(*param); | 688 | if let Param::Normal(ty) = self.data().params[id] { |
687 | generics.fill_implicit_impl_trait_args(param); | 689 | let ty = self.data().type_refs.lookup(ty); |
690 | generics.fill_implicit_impl_trait_args(ty); | ||
691 | } | ||
688 | } | 692 | } |
689 | } | 693 | } |
690 | GenericsOwner::Struct | 694 | GenericsOwner::Struct |
@@ -769,6 +773,11 @@ impl Ctx { | |||
769 | self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), | 773 | self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), |
770 | )) | 774 | )) |
771 | } | 775 | } |
776 | fn next_param_idx(&self) -> Idx<Param> { | ||
777 | Idx::from_raw(RawIdx::from( | ||
778 | self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32), | ||
779 | )) | ||
780 | } | ||
772 | } | 781 | } |
773 | 782 | ||
774 | fn desugar_future_path(orig: TypeRef) -> Path { | 783 | fn desugar_future_path(orig: TypeRef) -> Path { |