diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 85a43de6ff..5b9da17231 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -133,7 +133,8 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let mut item_tree = ctx.lower_block(&block); - if item_tree.data.is_empty() + if item_tree.small_data.is_empty() + && item_tree.big_data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() && item_tree.top_attrs.is_empty() @@ -143,7 +144,8 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc Arc::new(ItemTree { top_level: Box::new([]), attrs: FxHashMap::default(), - data: FxHashMap::default(), + small_data: FxHashMap::default(), + big_data: FxHashMap::default(), top_attrs: RawAttrs::EMPTY, vis: ItemVisibilities { arena: ThinVec::new() }, }) @@ -162,7 +164,8 @@ pub struct ItemTree { attrs: FxHashMap, RawAttrs>, vis: ItemVisibilities, // FIXME: They values store the key, turn this into a FxHashSet instead? - data: FxHashMap, ModItem>, + big_data: FxHashMap, BigModItem>, + small_data: FxHashMap, SmallModItem>, } impl ItemTree { @@ -204,13 +207,18 @@ impl ItemTree { let mut mods = 0; let mut macro_calls = 0; let mut macro_rules = 0; - for item in self.data.values() { + for item in self.small_data.values() { match item { - ModItem::Trait(_) => traits += 1, - ModItem::Impl(_) => impls += 1, - ModItem::Mod(_) => mods += 1, - ModItem::MacroCall(_) => macro_calls += 1, - ModItem::MacroRules(_) => macro_rules += 1, + SmallModItem::Trait(_) => traits += 1, + SmallModItem::Impl(_) => impls += 1, + SmallModItem::MacroRules(_) => macro_rules += 1, + _ => {} + } + } + for item in self.big_data.values() { + match item { + BigModItem::Mod(_) => mods += 1, + BigModItem::MacroCall(_) => macro_calls += 1, _ => {} } } @@ -222,9 +230,10 @@ impl ItemTree { } fn shrink_to_fit(&mut self) { - let ItemTree { top_level: _, attrs, data, vis: _, top_attrs: _ } = self; + let ItemTree { top_level: _, attrs, big_data, small_data, vis: _, top_attrs: _ } = self; attrs.shrink_to_fit(); - data.shrink_to_fit(); + big_data.shrink_to_fit(); + small_data.shrink_to_fit(); } } @@ -234,35 +243,37 @@ struct ItemVisibilities { } #[derive(Debug, Clone, Eq, PartialEq)] -enum ModItem { +enum SmallModItem { Const(Const), Enum(Enum), - // 32 - ExternBlock(ExternBlock), - // 40 - ExternCrate(ExternCrate), Function(Function), Impl(Impl), Macro2(Macro2), - // 32 - MacroCall(MacroCall), MacroRules(MacroRules), - // 40 - Mod(Mod), Static(Static), - // 32 - Struct(Struct), Trait(Trait), TraitAlias(TraitAlias), TypeAlias(TypeAlias), Union(Union), - // 40 +} + +#[derive(Debug, Clone, Eq, PartialEq)] +enum BigModItem { + ExternBlock(ExternBlock), + ExternCrate(ExternCrate), + MacroCall(MacroCall), + Mod(Mod), + Struct(Struct), Use(Use), } -// `ModItem` is stored a bunch in `ItemTree`'s so we pay the max for each item. It should stay as small as possible. +// `ModItem` is stored a bunch in `ItemTree`'s so we pay the max for each item. It should stay as +// small as possible which is why we split them in two, most common ones are 3 usize but some rarer +// ones are 5. #[cfg(target_pointer_width = "64")] -const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 5]>()]; +const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 5]>()]; +#[cfg(target_pointer_width = "64")] +const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 3]>()]; #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { @@ -343,9 +354,12 @@ macro_rules! mod_items { impl Index> for ItemTree { type Output = $typ; + #[allow(unused_imports)] fn index(&self, index: FileAstId<$ast>) -> &Self::Output { - match &self.data[&index.upcast()] { - ModItem::$typ(item) => item, + use BigModItem::*; + use SmallModItem::*; + match &self.$fld[&index.upcast()] { + $typ(item) => item, _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), } } @@ -356,23 +370,23 @@ macro_rules! mod_items { mod_items! { ModItemId -> - Use in uses -> ast::Use, - ExternCrate in extern_crates -> ast::ExternCrate, - ExternBlock in extern_blocks -> ast::ExternBlock, - Function in functions -> ast::Fn, - Struct in structs -> ast::Struct, - Union in unions -> ast::Union, - Enum in enums -> ast::Enum, - Const in consts -> ast::Const, - Static in statics -> ast::Static, - Trait in traits -> ast::Trait, - TraitAlias in trait_aliases -> ast::TraitAlias, - Impl in impls -> ast::Impl, - TypeAlias in type_aliases -> ast::TypeAlias, - Mod in mods -> ast::Module, - MacroCall in macro_calls -> ast::MacroCall, - MacroRules in macro_rules -> ast::MacroRules, - Macro2 in macro_defs -> ast::MacroDef, + Use in big_data -> ast::Use, + ExternCrate in big_data -> ast::ExternCrate, + ExternBlock in big_data -> ast::ExternBlock, + Function in small_data -> ast::Fn, + Struct in big_data -> ast::Struct, + Union in small_data -> ast::Union, + Enum in small_data -> ast::Enum, + Const in small_data -> ast::Const, + Static in small_data -> ast::Static, + Trait in small_data -> ast::Trait, + TraitAlias in small_data -> ast::TraitAlias, + Impl in small_data -> ast::Impl, + TypeAlias in small_data -> ast::TypeAlias, + Mod in big_data -> ast::Module, + MacroCall in big_data -> ast::MacroCall, + MacroRules in small_data -> ast::MacroRules, + Macro2 in small_data -> ast::MacroDef, } impl Index for ItemTree { @@ -421,6 +435,7 @@ pub struct UseTree { } // FIXME: Would be nice to encode `None` into this +// We could just use a `Name` where `_` well means `_` .. #[derive(Debug, Clone, PartialEq, Eq)] pub enum ImportAlias { /// Unnamed alias, as in `use Foo as _;` diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index ab60b7ad70..6ae745bb9a 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -20,10 +20,11 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, Interned, - ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, ModItem, ModItemId, ModKind, - ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, - TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, + BigModItem, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, + ImportAlias, Interned, ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, + ModItemId, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, SmallModItem, + Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, + VisibilityExplicitness, }, }; @@ -168,7 +169,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(strukt); let shape = adt_shape(strukt.kind()); let res = Struct { name, visibility, shape, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Struct(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::Struct(res)); Some(ast_id) } @@ -178,7 +179,7 @@ impl<'a> Ctx<'a> { let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Union(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Union(res)); Some(ast_id) } @@ -187,7 +188,7 @@ impl<'a> Ctx<'a> { let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Enum(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Enum(res)); Some(ast_id) } @@ -199,7 +200,7 @@ impl<'a> Ctx<'a> { let res = Function { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Function(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Function(res)); Some(ast_id) } @@ -211,7 +212,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); let res = TypeAlias { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::TypeAlias(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TypeAlias(res)); Some(ast_id) } @@ -220,7 +221,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); let res = Static { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Static(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Static(res)); Some(ast_id) } @@ -229,7 +230,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); let res = Const { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Const(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Const(res)); ast_id } @@ -251,7 +252,7 @@ impl<'a> Ctx<'a> { }; let ast_id = self.source_ast_id_map.ast_id(module); let res = Mod { name, visibility, kind, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Mod(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::Mod(res)); Some(ast_id) } @@ -261,7 +262,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(trait_def); let def = Trait { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Trait(def)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Trait(def)); Some(ast_id) } @@ -274,7 +275,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); let alias = TraitAlias { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::TraitAlias(alias)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TraitAlias(alias)); Some(ast_id) } @@ -283,7 +284,7 @@ impl<'a> Ctx<'a> { // Note that trait impls don't get implicit `Self` unlike traits, because here they are a // type alias rather than a type parameter, so this is handled by the resolver. let res = Impl { ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Impl(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Impl(res)); ast_id } @@ -295,7 +296,7 @@ impl<'a> Ctx<'a> { })?; let res = Use { visibility, ast_id, use_tree }; - self.tree.data.insert(ast_id.upcast(), ModItem::Use(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::Use(res)); Some(ast_id) } @@ -311,7 +312,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(extern_crate); let res = ExternCrate { name, alias, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::ExternCrate(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternCrate(res)); Some(ast_id) } @@ -325,7 +326,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let expand_to = hir_expand::ExpandTo::from_call_site(m); let res = MacroCall { path, ast_id, expand_to, ctxt: span_map.span_for_range(range).ctx }; - self.tree.data.insert(ast_id.upcast(), ModItem::MacroCall(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::MacroCall(res)); Some(ast_id) } @@ -334,7 +335,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let res = MacroRules { name: name.as_name(), ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::MacroRules(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroRules(res)); Some(ast_id) } @@ -345,7 +346,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(m); let res = Macro2 { name: name.as_name(), ast_id, visibility }; - self.tree.data.insert(ast_id.upcast(), ModItem::Macro2(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Macro2(res)); Some(ast_id) } @@ -372,7 +373,7 @@ impl<'a> Ctx<'a> { }); let res = ExternBlock { ast_id, children }; - self.tree.data.insert(ast_id.upcast(), ModItem::ExternBlock(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternBlock(res)); ast_id } diff --git a/crates/intern/src/symbol.rs b/crates/intern/src/symbol.rs index 3b962a86f1..8b2d6e8717 100644 --- a/crates/intern/src/symbol.rs +++ b/crates/intern/src/symbol.rs @@ -112,7 +112,6 @@ impl TaggedArcPtr { } } -// FIXME: This should have more than one niche #[derive(PartialEq, Eq, Hash)] pub struct Symbol { repr: TaggedArcPtr,