diff options
| author | Max Heller <max.a.heller@gmail.com> | 2023-08-05 08:00:39 -0400 |
|---|---|---|
| committer | Max Heller <max.a.heller@gmail.com> | 2023-08-05 08:00:39 -0400 |
| commit | 50db877bfa8a03dfaddb80f03737d62bce38f9a5 (patch) | |
| tree | eb1f66cfb7e2d18cac4fa3e284b72d572a9237a9 | |
| parent | 3205ed7a41ef016d0b445cf723c3eb5684956270 (diff) | |
| download | rust-50db877bfa8a03dfaddb80f03737d62bce38f9a5.tar.gz rust-50db877bfa8a03dfaddb80f03737d62bce38f9a5.zip | |
optimization and #[cfg] filtering for function generic params
| -rw-r--r-- | crates/hir-def/src/generics.rs | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index b0fb27e81d9..540fa115a00 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -159,17 +159,47 @@ impl GenericParams { 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| { + + // Returns the generic parameters that are enabled under the current `#[cfg]` options + let enabled_params = |params: &Interned<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(), - }) + + // In the common case, no parameters will by disabled by `#[cfg]` attributes. + // Therefore, make a first pass to check if all parameters are enabled and, if so, + // clone the `Interned<GenericParams>` instead of recreating an identical copy. + let all_type_or_consts_enabled = + params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); + let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); + + if all_type_or_consts_enabled && all_lifetimes_enabled { + params.clone() + } else { + Interned::new(GenericParams { + type_or_consts: all_type_or_consts_enabled + .then(|| params.type_or_consts.clone()) + .unwrap_or_else(|| { + params + .type_or_consts + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + lifetimes: all_lifetimes_enabled + .then(|| params.lifetimes.clone()) + .unwrap_or_else(|| { + 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) => {{ @@ -186,7 +216,8 @@ impl GenericParams { let tree = loc.id.item_tree(db); let item = &tree[loc.id.value]; - let mut generic_params = GenericParams::clone(&item.explicit_generic_params); + let enabled_params = enabled_params(&item.explicit_generic_params, &tree); + let mut generic_params = GenericParams::clone(&enabled_params); let module = loc.container.module(db); let func_data = db.function_data(id); |
