Skip to content

Commit 50db877

Browse files
committed
optimization and #[cfg] filtering for function generic params
1 parent 3205ed7 commit 50db877

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

crates/hir-def/src/generics.rs

+42-11
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,47 @@ impl GenericParams {
159159
let krate = def.module(db).krate;
160160
let cfg_options = db.crate_graph();
161161
let cfg_options = &cfg_options[krate].cfg_options;
162-
let enabled_params = |params: &GenericParams, item_tree: &ItemTree| {
162+
163+
// Returns the generic parameters that are enabled under the current `#[cfg]` options
164+
let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
163165
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
164-
Interned::new(GenericParams {
165-
type_or_consts: (params.type_or_consts.iter())
166-
.filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone()))
167-
.collect(),
168-
lifetimes: (params.lifetimes.iter())
169-
.filter_map(|(idx, param)| enabled(idx.into()).then(|| param.clone()))
170-
.collect(),
171-
where_predicates: params.where_predicates.clone(),
172-
})
166+
167+
// In the common case, no parameters will by disabled by `#[cfg]` attributes.
168+
// Therefore, make a first pass to check if all parameters are enabled and, if so,
169+
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
170+
let all_type_or_consts_enabled =
171+
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
172+
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));
173+
174+
if all_type_or_consts_enabled && all_lifetimes_enabled {
175+
params.clone()
176+
} else {
177+
Interned::new(GenericParams {
178+
type_or_consts: all_type_or_consts_enabled
179+
.then(|| params.type_or_consts.clone())
180+
.unwrap_or_else(|| {
181+
params
182+
.type_or_consts
183+
.iter()
184+
.filter_map(|(idx, param)| {
185+
enabled(idx.into()).then(|| param.clone())
186+
})
187+
.collect()
188+
}),
189+
lifetimes: all_lifetimes_enabled
190+
.then(|| params.lifetimes.clone())
191+
.unwrap_or_else(|| {
192+
params
193+
.lifetimes
194+
.iter()
195+
.filter_map(|(idx, param)| {
196+
enabled(idx.into()).then(|| param.clone())
197+
})
198+
.collect()
199+
}),
200+
where_predicates: params.where_predicates.clone(),
201+
})
202+
}
173203
};
174204
macro_rules! id_to_generics {
175205
($id:ident) => {{
@@ -186,7 +216,8 @@ impl GenericParams {
186216
let tree = loc.id.item_tree(db);
187217
let item = &tree[loc.id.value];
188218

189-
let mut generic_params = GenericParams::clone(&item.explicit_generic_params);
219+
let enabled_params = enabled_params(&item.explicit_generic_params, &tree);
220+
let mut generic_params = GenericParams::clone(&enabled_params);
190221

191222
let module = loc.container.module(db);
192223
let func_data = db.function_data(id);

0 commit comments

Comments
 (0)