From 8d4f40e8815970d549ba31a47c3c5660e624d37f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 8 Jan 2022 11:04:16 +0100 Subject: [PATCH] Do less allocs in `trait_data` and `impl_data` queries --- crates/hir_def/src/data.rs | 87 +++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index f08be39128a..471c7330d73 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -184,6 +184,7 @@ pub struct TraitData { /// method calls to this trait's methods when the receiver is an array and the crate edition is /// 2015 or 2018. pub skip_array_during_method_dispatch: bool, + // box it as the vec is usually empty anyways pub attribute_calls: Option, MacroCallId)>>>, } @@ -208,17 +209,8 @@ pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc, pub items: Vec, pub is_negative: bool, + // box it as the vec is usually empty anyways pub attribute_calls: Option, MacroCallId)>>>, } @@ -280,18 +273,15 @@ pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc let container = ItemContainerId::ImplId(id); let mut expander = Expander::new(db, impl_loc.id.file_id(), module_id); - let (attribute_calls, items) = collect_items( + let (items, attribute_calls) = do_collect( db, module_id, &mut expander, - impl_def.items.iter().copied(), + &impl_def.items, impl_loc.id.tree_id(), container, - 100, ); let items = items.into_iter().map(|(_, item)| item).collect(); - let attribute_calls = - if attribute_calls.is_empty() { None } else { Some(Box::new(attribute_calls)) }; Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }) } @@ -348,17 +338,47 @@ pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc (Vec<(Name, AssocItemId)>, Option, MacroCallId)>>>) { + let mut items = Vec::new(); + let mut attribute_calls = Vec::new(); + + collect_items( + db, + &mut items, + &mut attribute_calls, + module_id, + expander, + assoc_items.iter().copied(), + tree_id, + container, + 100, + ); + + let attribute_calls = + if attribute_calls.is_empty() { None } else { Some(Box::new(attribute_calls)) }; + (items, attribute_calls) +} + fn collect_items( db: &dyn DefDatabase, + items: &mut Vec<(Name, AssocItemId)>, + attr_calls: &mut Vec<(AstId, MacroCallId)>, module: ModuleId, expander: &mut Expander, assoc_items: impl Iterator, tree_id: item_tree::TreeId, container: ItemContainerId, limit: usize, -) -> (Vec<(AstId, MacroCallId)>, Vec<(Name, AssocItemId)>) { +) { if limit == 0 { - return Default::default(); + return; } let item_tree = tree_id.item_tree(db); @@ -366,26 +386,22 @@ fn collect_items( let cfg_options = &crate_graph[module.krate].cfg_options; let def_map = module.def_map(db); - let mut items = Vec::new(); - let mut attribute_calls = Vec::new(); - 'items: for item in assoc_items { let attrs = item_tree.attrs(db, module.krate, ModItem::from(item).into()); if !attrs.is_cfg_enabled(cfg_options) { continue; } + for attr in &*attrs { let ast_id = AstId::new(expander.current_file_id(), item.ast_id(&item_tree).upcast()); let ast_id_with_path = AstIdWithPath { path: (*attr.path).clone(), ast_id }; + if let Ok(ResolvedAttr::Macro(call_id)) = def_map.resolve_attr_macro(db, module.local_id, ast_id_with_path, attr) { - attribute_calls.push((ast_id, call_id)); + attr_calls.push((ast_id, call_id)); let res = expander.enter_expand_id(db, call_id); - let (mac_attrs, mac_items) = - collect_macro_items(db, module, expander, container, limit, res); - items.extend(mac_items); - attribute_calls.extend(mac_attrs); + collect_macro_items(db, items, attr_calls, module, expander, container, limit, res); continue 'items; } } @@ -419,37 +435,32 @@ fn collect_items( let res = expander.enter_expand(db, call); if let Ok(res) = res { - let (mac_attrs, mac_items) = - collect_macro_items(db, module, expander, container, limit, res); - items.extend(mac_items); - attribute_calls.extend(mac_attrs); + collect_macro_items( + db, items, attr_calls, module, expander, container, limit, res, + ); } } } } - - (attribute_calls, items) } fn collect_macro_items( db: &dyn DefDatabase, + items: &mut Vec<(Name, AssocItemId)>, + attr_calls: &mut Vec<(AstId, MacroCallId)>, module: ModuleId, expander: &mut Expander, container: ItemContainerId, limit: usize, res: ExpandResult>, -) -> (Vec<(AstId, MacroCallId)>, Vec<(Name, AssocItemId)>) { +) { if let Some((mark, mac)) = res.value { let src: InFile = expander.to_source(mac); let tree_id = item_tree::TreeId::new(src.file_id, None); let item_tree = tree_id.item_tree(db); let iter = item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item); - let items = collect_items(db, module, expander, iter, tree_id, container, limit - 1); + collect_items(db, items, attr_calls, module, expander, iter, tree_id, container, limit - 1); expander.exit(db, mark); - - return items; } - - Default::default() }