Unnamed repository; edit this file 'description' to name the repository.
handle `#[cfg]`s on generic parameters
Max Heller 2023-07-28
parent b64e5b3 · commit 008b639
-rw-r--r--crates/hir-def/src/generics.rs19
-rw-r--r--crates/hir-def/src/item_tree.rs15
-rw-r--r--crates/hir-def/src/item_tree/lower.rs35
3 files changed, 65 insertions, 4 deletions
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<GenericParams> {
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<Variant>),
Field(Idx<Field>),
Param(Idx<Param>),
+ TypeOrConstParamData(Idx<TypeOrConstParamData>),
+ LifetimeParamData(Idx<LifetimeParamData>),
}
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<Variant>), Field(Idx<Field>), Param(Idx<Param>));
+from_attrs!(
+ ModItem(ModItem),
+ Variant(Idx<Variant>),
+ Field(Idx<Field>),
+ Param(Idx<Param>),
+ TypeOrConstParamData(Idx<TypeOrConstParamData>),
+ LifetimeParamData(Idx<LifetimeParamData>),
+);
/// 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 &param {
+ ast::GenericParam::ConstParam(param) => param.name()?.as_name(),
+ ast::GenericParam::LifetimeParam(param) => {
+ Name::new_lifetime(&param.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(&param.name) {
+ self.add_attrs(
+ idx.into(),
+ RawAttrs::new(self.db.upcast(), param, self.hygiene()),
+ );
+ }
+ }
+ }
+
Interned::new(generics)
}