diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index d7d44e4138..6fe429c8d9 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -21,6 +21,7 @@ use crate::{ db::DefDatabase, dyn_map::{keys, DynMap}, expander::Expander, + item_tree::ItemTree, lower::LowerCtx, nameres::{DefMap, MacroSubNs}, src::{HasChildSource, HasSource}, @@ -154,12 +155,28 @@ impl GenericParams { def: GenericDefId, ) -> Interned { let _p = profile::span("generic_params_query"); + + let krate = def.module(db).krate; + let cfg_options = db.crate_graph(); + let cfg_options = &cfg_options[krate].cfg_options; + let enabled_params = |params: &GenericParams, item_tree: &ItemTree| { + let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); + Interned::new(GenericParams { + type_or_consts: (params.type_or_consts.iter()) + .filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone())) + .collect(), + lifetimes: (params.lifetimes.iter()) + .filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone())) + .collect(), + where_predicates: params.where_predicates.clone(), + }) + }; macro_rules! id_to_generics { ($id:ident) => {{ let id = $id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - item.generic_params.clone() + enabled_params(&item.generic_params, &tree) }}; } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 6f80bb6e07..96c176d60f 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -64,7 +64,7 @@ use triomphe::Arc; use crate::{ attr::Attrs, db::DefDatabase, - generics::GenericParams, + generics::{GenericParams, LifetimeParamData, TypeOrConstParamData}, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, @@ -296,10 +296,12 @@ pub enum AttrOwner { Variant(Idx), Field(Idx), Param(Idx), + TypeOrConstParamData(Idx), + LifetimeParamData(Idx), } macro_rules! from_attrs { - ( $( $var:ident($t:ty) ),+ ) => { + ( $( $var:ident($t:ty) ),+ $(,)? ) => { $( impl From<$t> for AttrOwner { fn from(t: $t) -> AttrOwner { @@ -310,7 +312,14 @@ macro_rules! from_attrs { }; } -from_attrs!(ModItem(ModItem), Variant(Idx), Field(Idx), Param(Idx)); +from_attrs!( + ModItem(ModItem), + Variant(Idx), + Field(Idx), + Param(Idx), + TypeOrConstParamData(Idx), + LifetimeParamData(Idx), +); /// Trait implemented by all item nodes in the item tree. pub trait ItemTreeNode: Clone { diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 46633667ed..7dffd6fc18 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -605,6 +605,41 @@ impl<'a> Ctx<'a> { generics.fill(&self.body_ctx, node); generics.shrink_to_fit(); + + if let Some(params) = node.generic_param_list() { + let params_by_name: FxHashMap<_, _> = params + .generic_params() + .filter_map(|param| { + let name = match ¶m { + ast::GenericParam::ConstParam(param) => param.name()?.as_name(), + ast::GenericParam::LifetimeParam(param) => { + Name::new_lifetime(¶m.lifetime()?) + } + ast::GenericParam::TypeParam(param) => param.name()?.as_name(), + }; + Some((name, param)) + }) + .collect(); + for (idx, param) in generics.type_or_consts.iter() { + if let Some(name) = param.name() { + if let Some(param) = params_by_name.get(name) { + self.add_attrs( + idx.into(), + RawAttrs::new(self.db.upcast(), param, self.hygiene()), + ); + } + } + } + for (idx, param) in generics.lifetimes.iter() { + if let Some(param) = params_by_name.get(¶m.name) { + self.add_attrs( + idx.into(), + RawAttrs::new(self.db.upcast(), param, self.hygiene()), + ); + } + } + } + Interned::new(generics) }