handle #[cfg]s on generic parameters

This commit is contained in:
Max Heller 2023-07-27 21:17:10 -04:00
parent b64e5b3919
commit 008b639ef5
3 changed files with 65 additions and 4 deletions

View file

@ -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)
}};
}

View file

@ -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 {

View file

@ -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)
}