about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMax Heller <max.a.heller@gmail.com>2023-08-05 08:00:39 -0400
committerMax Heller <max.a.heller@gmail.com>2023-08-05 08:00:39 -0400
commit50db877bfa8a03dfaddb80f03737d62bce38f9a5 (patch)
treeeb1f66cfb7e2d18cac4fa3e284b72d572a9237a9
parent3205ed7a41ef016d0b445cf723c3eb5684956270 (diff)
downloadrust-50db877bfa8a03dfaddb80f03737d62bce38f9a5.tar.gz
rust-50db877bfa8a03dfaddb80f03737d62bce38f9a5.zip
optimization and #[cfg] filtering for function generic params
-rw-r--r--crates/hir-def/src/generics.rs53
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);