From e9f8ecab45bf345e25f7a2f1a786ea7e25631b68 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 09:46:01 +0200 Subject: [PATCH 01/14] Remove `ItemTreeId` --- crates/hir-def/src/attr.rs | 19 ++++++--- crates/hir-def/src/item_tree.rs | 53 ------------------------- crates/hir-def/src/nameres.rs | 34 +++++++++------- crates/hir-def/src/nameres/collector.rs | 32 +++++++++------ 4 files changed, 52 insertions(+), 86 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index a7328809a8..cc9a2fdf4c 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -523,10 +523,15 @@ impl AttrsWithOwner { let mod_data = &def_map[module.local_id]; let raw_attrs = match mod_data.origin { - ModuleOrigin::File { definition, declaration_tree_id, .. } => { + ModuleOrigin::File { + definition, + declaration_tree_id, + file_item_tree_id, + .. + } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into())) + .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) .clone(); let tree = db.file_item_tree(definition.into()); let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); @@ -536,10 +541,12 @@ impl AttrsWithOwner { let tree = db.file_item_tree(definition.into()); tree.raw_attrs(AttrOwner::TopLevel).clone() } - ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id - .item_tree(db) - .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into())) - .clone(), + ModuleOrigin::Inline { definition_tree_id, file_item_tree_id, .. } => { + definition_tree_id + .item_tree(db) + .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) + .clone() + } ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); tree.raw_attrs(AttrOwner::TopLevel).clone() diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 81c8f56456..ec2b65c9c0 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -404,59 +404,6 @@ impl TreeId { } } -#[derive(Debug)] -pub struct ItemTreeId { - tree: TreeId, - pub value: FileItemTreeId, -} - -impl ItemTreeId { - pub fn new(tree: TreeId, idx: FileItemTreeId) -> Self { - Self { tree, value: idx } - } - - pub fn file_id(self) -> HirFileId { - self.tree.file - } - - pub fn tree_id(self) -> TreeId { - self.tree - } - - pub fn item_tree(self, db: &dyn DefDatabase) -> Arc { - self.tree.item_tree(db) - } - - pub fn resolved(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R - where - ItemTree: Index, Output = N>, - { - cb(&self.tree.item_tree(db)[self.value]) - } -} - -impl Copy for ItemTreeId {} -impl Clone for ItemTreeId { - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq for ItemTreeId { - fn eq(&self, other: &Self) -> bool { - self.tree == other.tree && self.value == other.value - } -} - -impl Eq for ItemTreeId {} - -impl Hash for ItemTreeId { - fn hash(&self, state: &mut H) { - self.tree.hash(state); - self.value.hash(state); - } -} - macro_rules! mod_items { ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index c908e45754..e62fd3dab7 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -80,7 +80,7 @@ use crate::{ LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, db::DefDatabase, item_scope::{BuiltinShadowMode, ItemScope}, - item_tree::{ItemTreeId, Mod, TreeId}, + item_tree::{FileItemTreeId, Mod, TreeId}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, @@ -289,11 +289,13 @@ pub enum ModuleOrigin { File { is_mod_rs: bool, declaration: FileAstId, - declaration_tree_id: ItemTreeId, + declaration_tree_id: TreeId, + file_item_tree_id: FileItemTreeId, definition: EditionedFileId, }, Inline { - definition_tree_id: ItemTreeId, + definition_tree_id: TreeId, + file_item_tree_id: FileItemTreeId, definition: FileAstId, }, /// Pseudo-module introduced by a block scope (contains only inner items). @@ -309,7 +311,7 @@ impl ModuleOrigin { &ModuleOrigin::File { declaration, declaration_tree_id, .. } => { Some(AstId::new(declaration_tree_id.file_id(), declaration)) } - &ModuleOrigin::Inline { definition, definition_tree_id } => { + &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { Some(AstId::new(definition_tree_id.file_id(), definition)) } ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, @@ -341,12 +343,14 @@ impl ModuleOrigin { let sf = db.parse(editioned_file_id).tree(); InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf)) } - &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( - definition_tree_id.file_id(), - ModuleSource::Module( - AstId::new(definition_tree_id.file_id(), definition).to_node(db), - ), - ), + &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { + InFile::new( + definition_tree_id.file_id(), + ModuleSource::Module( + AstId::new(definition_tree_id.file_id(), definition).to_node(db), + ), + ) + } ModuleOrigin::BlockExpr { block, .. } => { InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db))) } @@ -773,10 +777,12 @@ impl ModuleData { ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db), ) } - &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( - definition_tree_id.file_id(), - AstId::new(definition_tree_id.file_id(), definition).to_range(db), - ), + &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { + InFile::new( + definition_tree_id.file_id(), + AstId::new(definition_tree_id.file_id(), definition).to_range(db), + ) + } ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)), } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 34a129a88e..e2231857fd 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeId, - ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, + self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeNode, Macro2, + MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -140,7 +140,8 @@ struct ImportSource { id: UseId, is_prelude: bool, kind: ImportKind, - item_tree_id: ItemTreeId, + tree: TreeId, + item: FileItemTreeId, } #[derive(Debug, Eq, PartialEq)] @@ -154,19 +155,20 @@ struct Import { impl Import { fn from_use( tree: &ItemTree, - item_tree_id: ItemTreeId, + tree_id: TreeId, + item: FileItemTreeId, id: UseId, is_prelude: bool, mut cb: impl FnMut(Self), ) { - let it = &tree[item_tree_id.value]; + let it = &tree[item]; let visibility = &tree[it.visibility]; it.use_tree.expand(|idx, path, kind, alias| { cb(Self { path, alias, visibility: visibility.clone(), - source: ImportSource { use_tree: idx, id, is_prelude, kind, item_tree_id }, + source: ImportSource { use_tree: idx, id, is_prelude, kind, tree: tree_id, item }, }); }); } @@ -860,7 +862,8 @@ impl DefCollector<'_> { kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), id, use_tree, - item_tree_id, + tree, + item, .. } => { let name = match &import.alias { @@ -893,8 +896,8 @@ impl DefCollector<'_> { let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { return false; }; - let item_tree = item_tree_id.item_tree(self.db); - let use_kind = item_tree[item_tree_id.value].use_tree.kind(); + let item_tree = tree.item_tree(self.db); + let use_kind = item_tree[item].use_tree.kind(); let UseTreeKind::Single { path, .. } = use_kind else { return false; }; @@ -1643,7 +1646,7 @@ impl DefCollector<'_> { Import { ref path, source: - ImportSource { use_tree, id, is_prelude: _, kind: _, item_tree_id: _ }, + ImportSource { use_tree, id, is_prelude: _, kind: _, tree: _, item: _ }, .. }, .. @@ -1771,7 +1774,8 @@ impl ModCollector<'_, '_> { let is_prelude = attrs.by_key(sym::prelude_import).exists(); Import::from_use( self.item_tree, - ItemTreeId::new(self.tree_id, item_tree_id), + self.tree_id, + item_tree_id, id, is_prelude, |import| { @@ -2207,13 +2211,15 @@ impl ModCollector<'_, '_> { let origin = match definition { None => ModuleOrigin::Inline { definition: declaration, - definition_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id), + definition_tree_id: self.tree_id, + file_item_tree_id: mod_tree_id, }, Some((definition, is_mod_rs)) => ModuleOrigin::File { declaration, definition, is_mod_rs, - declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id), + declaration_tree_id: self.tree_id, + file_item_tree_id: mod_tree_id, }, }; From f3434f537f3f4409b44c99e7c688f71dee42554d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 10:17:45 +0200 Subject: [PATCH 02/14] Remove `FileItemTreeId` --- crates/hir-def/src/attr.rs | 19 ++-- crates/hir-def/src/item_tree.rs | 115 +++++++----------------- crates/hir-def/src/item_tree/lower.rs | 102 +++++++++++---------- crates/hir-def/src/nameres.rs | 30 +++---- crates/hir-def/src/nameres/collector.rs | 31 +++---- 5 files changed, 116 insertions(+), 181 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index cc9a2fdf4c..e1bf6fde8a 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -523,15 +523,10 @@ impl AttrsWithOwner { let mod_data = &def_map[module.local_id]; let raw_attrs = match mod_data.origin { - ModuleOrigin::File { - definition, - declaration_tree_id, - file_item_tree_id, - .. - } => { + ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) + .raw_attrs(AttrOwner::ModItem(declaration.into())) .clone(); let tree = db.file_item_tree(definition.into()); let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); @@ -541,12 +536,10 @@ impl AttrsWithOwner { let tree = db.file_item_tree(definition.into()); tree.raw_attrs(AttrOwner::TopLevel).clone() } - ModuleOrigin::Inline { definition_tree_id, file_item_tree_id, .. } => { - definition_tree_id - .item_tree(db) - .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) - .clone() - } + ModuleOrigin::Inline { definition_tree_id, definition } => definition_tree_id + .item_tree(db) + .raw_attrs(AttrOwner::ModItem(definition.into())) + .clone(), ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); tree.raw_attrs(AttrOwner::TopLevel).clone() diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index ec2b65c9c0..578f5fdee2 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -37,8 +37,8 @@ mod tests; use std::{ fmt::{self, Debug}, - hash::{Hash, Hasher}, - ops::{Index, Range}, + hash::Hash, + ops::Index, sync::OnceLock, }; @@ -51,7 +51,7 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::{Arena, Idx, RawIdx}; +use la_arena::{Arena, Idx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; @@ -277,23 +277,23 @@ struct ItemVisibilities { #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { - uses: Arena, - extern_crates: Arena, - extern_blocks: Arena, - functions: Arena, - structs: Arena, - unions: Arena, - enums: Arena, - consts: Arena, - statics: Arena, - traits: Arena, - trait_aliases: Arena, - impls: Arena, - type_aliases: Arena, - mods: Arena, - macro_calls: Arena, - macro_rules: Arena, - macro_defs: Arena, + uses: FxHashMap, Use>, + extern_crates: FxHashMap, ExternCrate>, + extern_blocks: FxHashMap, ExternBlock>, + functions: FxHashMap, Function>, + structs: FxHashMap, Struct>, + unions: FxHashMap, Union>, + enums: FxHashMap, Enum>, + consts: FxHashMap, Const>, + statics: FxHashMap, Static>, + traits: FxHashMap, Trait>, + trait_aliases: FxHashMap, TraitAlias>, + impls: FxHashMap, Impl>, + type_aliases: FxHashMap, TypeAlias>, + mods: FxHashMap, Mod>, + macro_calls: FxHashMap, MacroCall>, + macro_rules: FxHashMap, MacroRules>, + macro_defs: FxHashMap, Macro2>, vis: ItemVisibilities, } @@ -329,51 +329,11 @@ pub trait ItemTreeNode: Clone { fn ast_id(&self) -> FileAstId; /// Looks up an instance of `Self` in an item tree. - fn lookup(tree: &ItemTree, index: Idx) -> &Self; + fn lookup(tree: &ItemTree, index: FileAstId) -> &Self; } -pub struct FileItemTreeId(Idx); - -impl FileItemTreeId { - pub fn range_iter(range: Range) -> impl Iterator + Clone { - (range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32()) - .map(RawIdx::from_u32) - .map(Idx::from_raw) - .map(Self) - } -} - -impl FileItemTreeId { - pub fn index(&self) -> Idx { - self.0 - } -} - -impl Clone for FileItemTreeId { - fn clone(&self) -> Self { - *self - } -} -impl Copy for FileItemTreeId {} - -impl PartialEq for FileItemTreeId { - fn eq(&self, other: &FileItemTreeId) -> bool { - self.0 == other.0 - } -} -impl Eq for FileItemTreeId {} - -impl Hash for FileItemTreeId { - fn hash(&self, state: &mut H) { - self.0.hash(state) - } -} - -impl fmt::Debug for FileItemTreeId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} +#[allow(type_alias_bounds)] +pub type ItemTreeAstId = FileAstId; /// Identifies a particular [`ItemTree`]. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] @@ -409,21 +369,21 @@ macro_rules! mod_items { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum ModItem { $( - $typ(FileItemTreeId<$typ>), + $typ(FileAstId<$ast>), )+ } impl ModItem { - pub fn ast_id(&self, tree: &ItemTree) -> FileAstId { + pub fn ast_id(self) -> FileAstId { match self { - $(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+ + $(ModItem::$typ(it) => it.upcast()),+ } } } $( - impl From> for ModItem { - fn from(id: FileItemTreeId<$typ>) -> ModItem { + impl From> for ModItem { + fn from(id: FileAstId<$ast>) -> ModItem { ModItem::$typ(id) } } @@ -433,20 +393,20 @@ macro_rules! mod_items { impl ItemTreeNode for $typ { type Source = $ast; - fn ast_id(&self) -> FileAstId { + fn ast_id(&self) -> FileAstId<$ast> { self.ast_id } - fn lookup(tree: &ItemTree, index: Idx) -> &Self { - &tree.data().$fld[index] + fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self { + &tree.data().$fld[&index] } } - impl Index> for ItemTree { + impl Index> for ItemTree { type Output = $typ; - fn index(&self, index: Idx<$typ>) -> &Self::Output { - &self.data().$fld[index] + fn index(&self, index: FileAstId<$ast>) -> &Self::Output { + &self.data().$fld[&index] } } )+ @@ -506,13 +466,6 @@ impl Index for ItemTree { } } -impl Index> for ItemTree { - type Output = N; - fn index(&self, id: FileItemTreeId) -> &N { - N::lookup(self, id.index()) - } -} - #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { pub visibility: RawVisibilityId, diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 26d209c972..17b115b6ec 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -20,18 +20,14 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, FileItemTreeId, Function, - Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, - Mod, ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, + AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, + Interned, ItemTree, ItemTreeAstId, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, + ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, }, }; -fn id(index: Idx) -> FileItemTreeId { - FileItemTreeId(index) -} - pub(super) struct Ctx<'a> { db: &'a dyn DefDatabase, tree: ItemTree, @@ -173,36 +169,36 @@ impl<'a> Ctx<'a> { } } - fn lower_struct(&mut self, strukt: &ast::Struct) -> Option> { + fn lower_struct(&mut self, strukt: &ast::Struct) -> Option> { let visibility = self.lower_visibility(strukt); let name = strukt.name()?.as_name(); 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 }; - let id = id(self.data().structs.alloc(res)); + self.data().structs.insert(ast_id, res); - Some(id) + Some(ast_id) } - fn lower_union(&mut self, union: &ast::Union) -> Option> { + fn lower_union(&mut self, union: &ast::Union) -> Option> { let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, ast_id }; - let id = id(self.data().unions.alloc(res)); - Some(id) + self.data().unions.insert(ast_id, res); + Some(ast_id) } - fn lower_enum(&mut self, enum_: &ast::Enum) -> Option> { + fn lower_enum(&mut self, enum_: &ast::Enum) -> Option> { let visibility = self.lower_visibility(enum_); let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, ast_id }; - let id = id(self.data().enums.alloc(res)); - Some(id) + self.data().enums.insert(ast_id, res); + Some(ast_id) } - fn lower_function(&mut self, func: &ast::Fn) -> Option> { + fn lower_function(&mut self, func: &ast::Fn) -> Option> { let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); @@ -210,39 +206,41 @@ impl<'a> Ctx<'a> { let res = Function { name, visibility, ast_id }; - let id = id(self.data().functions.alloc(res)); - Some(id) + self.data().functions.insert(ast_id, res); + Some(ast_id) } fn lower_type_alias( &mut self, type_alias: &ast::TypeAlias, - ) -> Option> { + ) -> Option> { let name = type_alias.name()?.as_name(); 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 }; - let id = id(self.data().type_aliases.alloc(res)); - Some(id) + self.data().type_aliases.insert(ast_id, res); + Some(ast_id) } - fn lower_static(&mut self, static_: &ast::Static) -> Option> { + fn lower_static(&mut self, static_: &ast::Static) -> Option> { let name = static_.name()?.as_name(); let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); let res = Static { name, visibility, ast_id }; - Some(id(self.data().statics.alloc(res))) + self.data().statics.insert(ast_id, res); + Some(ast_id) } - fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId { + fn lower_const(&mut self, konst: &ast::Const) -> ItemTreeAstId { let name = konst.name().map(|it| it.as_name()); let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); let res = Const { name, visibility, ast_id }; - id(self.data().consts.alloc(res)) + self.data().consts.insert(ast_id, res); + ast_id } - fn lower_module(&mut self, module: &ast::Module) -> Option> { + fn lower_module(&mut self, module: &ast::Module) -> Option> { let name = module.name()?.as_name(); let visibility = self.lower_visibility(module); let kind = if module.semicolon_token().is_some() { @@ -260,41 +258,43 @@ impl<'a> Ctx<'a> { }; let ast_id = self.source_ast_id_map.ast_id(module); let res = Mod { name, visibility, kind, ast_id }; - Some(id(self.data().mods.alloc(res))) + self.data().mods.insert(ast_id, res); + Some(ast_id) } - fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option> { + fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option> { let name = trait_def.name()?.as_name(); let visibility = self.lower_visibility(trait_def); let ast_id = self.source_ast_id_map.ast_id(trait_def); let def = Trait { name, visibility, ast_id }; - let id = id(self.data().traits.alloc(def)); - Some(id) + self.data().traits.insert(ast_id, def); + Some(ast_id) } fn lower_trait_alias( &mut self, trait_alias_def: &ast::TraitAlias, - ) -> Option> { + ) -> Option> { let name = trait_alias_def.name()?.as_name(); let visibility = self.lower_visibility(trait_alias_def); let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); let alias = TraitAlias { name, visibility, ast_id }; - let id = id(self.data().trait_aliases.alloc(alias)); - Some(id) + self.data().trait_aliases.insert(ast_id, alias); + Some(ast_id) } - fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId { + fn lower_impl(&mut self, impl_def: &ast::Impl) -> ItemTreeAstId { let ast_id = self.source_ast_id_map.ast_id(impl_def); // 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 }; - id(self.data().impls.alloc(res)) + self.data().impls.insert(ast_id, res); + ast_id } - fn lower_use(&mut self, use_item: &ast::Use) -> Option> { + fn lower_use(&mut self, use_item: &ast::Use) -> Option> { let visibility = self.lower_visibility(use_item); let ast_id = self.source_ast_id_map.ast_id(use_item); let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| { @@ -302,13 +302,14 @@ impl<'a> Ctx<'a> { })?; let res = Use { visibility, ast_id, use_tree }; - Some(id(self.data().uses.alloc(res))) + self.data().uses.insert(ast_id, res); + Some(ast_id) } fn lower_extern_crate( &mut self, extern_crate: &ast::ExternCrate, - ) -> Option> { + ) -> Option> { let name = extern_crate.name_ref()?.as_name(); let alias = extern_crate.rename().map(|a| { a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) @@ -317,10 +318,11 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(extern_crate); let res = ExternCrate { name, alias, visibility, ast_id }; - Some(id(self.data().extern_crates.alloc(res))) + self.data().extern_crates.insert(ast_id, res); + Some(ast_id) } - fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option> { + fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option> { let span_map = self.span_map(); let path = m.path()?; let range = path.syntax().text_range(); @@ -330,28 +332,31 @@ 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 }; - Some(id(self.data().macro_calls.alloc(res))) + self.data().macro_calls.insert(ast_id, res); + Some(ast_id) } - fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option> { + fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option> { let name = m.name()?; let ast_id = self.source_ast_id_map.ast_id(m); let res = MacroRules { name: name.as_name(), ast_id }; - Some(id(self.data().macro_rules.alloc(res))) + self.data().macro_rules.insert(ast_id, res); + Some(ast_id) } - fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option> { + fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option> { let name = m.name()?; let ast_id = self.source_ast_id_map.ast_id(m); let visibility = self.lower_visibility(m); let res = Macro2 { name: name.as_name(), ast_id, visibility }; - Some(id(self.data().macro_defs.alloc(res))) + self.data().macro_defs.insert(ast_id, res); + Some(ast_id) } - fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId { + fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> ItemTreeAstId { let ast_id = self.source_ast_id_map.ast_id(block); let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| { list.extern_items() @@ -374,7 +379,8 @@ impl<'a> Ctx<'a> { }); let res = ExternBlock { ast_id, children }; - id(self.data().extern_blocks.alloc(res)) + self.data().extern_blocks.insert(ast_id, res); + ast_id } fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId { diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index e62fd3dab7..610bb6b00b 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -80,7 +80,7 @@ use crate::{ LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, db::DefDatabase, item_scope::{BuiltinShadowMode, ItemScope}, - item_tree::{FileItemTreeId, Mod, TreeId}, + item_tree::TreeId, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, @@ -290,12 +290,10 @@ pub enum ModuleOrigin { is_mod_rs: bool, declaration: FileAstId, declaration_tree_id: TreeId, - file_item_tree_id: FileItemTreeId, definition: EditionedFileId, }, Inline { definition_tree_id: TreeId, - file_item_tree_id: FileItemTreeId, definition: FileAstId, }, /// Pseudo-module introduced by a block scope (contains only inner items). @@ -311,7 +309,7 @@ impl ModuleOrigin { &ModuleOrigin::File { declaration, declaration_tree_id, .. } => { Some(AstId::new(declaration_tree_id.file_id(), declaration)) } - &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { + &ModuleOrigin::Inline { definition, definition_tree_id } => { Some(AstId::new(definition_tree_id.file_id(), definition)) } ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, @@ -343,14 +341,12 @@ impl ModuleOrigin { let sf = db.parse(editioned_file_id).tree(); InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf)) } - &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { - InFile::new( - definition_tree_id.file_id(), - ModuleSource::Module( - AstId::new(definition_tree_id.file_id(), definition).to_node(db), - ), - ) - } + &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( + definition_tree_id.file_id(), + ModuleSource::Module( + AstId::new(definition_tree_id.file_id(), definition).to_node(db), + ), + ), ModuleOrigin::BlockExpr { block, .. } => { InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db))) } @@ -777,12 +773,10 @@ impl ModuleData { ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db), ) } - &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { - InFile::new( - definition_tree_id.file_id(), - AstId::new(definition_tree_id.file_id(), definition).to_range(db), - ) - } + &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( + definition_tree_id.file_id(), + AstId::new(definition_tree_id.file_id(), definition).to_range(db), + ), ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)), } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index e2231857fd..a8ee92d813 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -35,7 +35,7 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeNode, Macro2, + self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, @@ -141,7 +141,7 @@ struct ImportSource { is_prelude: bool, kind: ImportKind, tree: TreeId, - item: FileItemTreeId, + item: FileAstId, } #[derive(Debug, Eq, PartialEq)] @@ -156,7 +156,7 @@ impl Import { fn from_use( tree: &ItemTree, tree_id: TreeId, - item: FileItemTreeId, + item: FileAstId, id: UseId, is_prelude: bool, mut cb: impl FnMut(Self), @@ -2084,7 +2084,7 @@ impl ModCollector<'_, '_> { ); } - fn collect_module(&mut self, module_id: FileItemTreeId, attrs: &Attrs) { + fn collect_module(&mut self, module_id: ItemTreeAstId, attrs: &Attrs) { let path_attr = attrs.by_key(sym::path).string_value_unescape(); let is_macro_use = attrs.by_key(sym::macro_use).exists(); let module = &self.item_tree[module_id]; @@ -2096,7 +2096,6 @@ impl ModCollector<'_, '_> { module.ast_id, None, &self.item_tree[module.visibility], - module_id, ); let Some(mod_dir) = @@ -2151,7 +2150,6 @@ impl ModCollector<'_, '_> { ast_id.value, Some((file_id, is_mod_rs)), &self.item_tree[module.visibility], - module_id, ); ModCollector { def_collector: self.def_collector, @@ -2179,7 +2177,6 @@ impl ModCollector<'_, '_> { ast_id.value, None, &self.item_tree[module.visibility], - module_id, ); self.def_collector.def_map.diagnostics.push( DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates), @@ -2196,7 +2193,6 @@ impl ModCollector<'_, '_> { declaration: FileAstId, definition: Option<(EditionedFileId, bool)>, visibility: &crate::visibility::RawVisibility, - mod_tree_id: FileItemTreeId, ) -> LocalModuleId { let def_map = &mut self.def_collector.def_map; let vis = def_map @@ -2209,17 +2205,14 @@ impl ModCollector<'_, '_> { ) .unwrap_or(Visibility::Public); let origin = match definition { - None => ModuleOrigin::Inline { - definition: declaration, - definition_tree_id: self.tree_id, - file_item_tree_id: mod_tree_id, - }, + None => { + ModuleOrigin::Inline { definition: declaration, definition_tree_id: self.tree_id } + } Some((definition, is_mod_rs)) => ModuleOrigin::File { declaration, definition, is_mod_rs, declaration_tree_id: self.tree_id, - file_item_tree_id: mod_tree_id, }, }; @@ -2294,11 +2287,7 @@ impl ModCollector<'_, '_> { attr.path.display(self.def_collector.db, Edition::LATEST) ); - let ast_id = AstIdWithPath::new( - self.file_id(), - mod_item.ast_id(self.item_tree), - attr.path.clone(), - ); + let ast_id = AstIdWithPath::new(self.file_id(), mod_item.ast_id(), attr.path.clone()); self.def_collector.unresolved_macros.push(MacroDirective { module_id: self.module_id, depth: self.macro_depth + 1, @@ -2317,7 +2306,7 @@ impl ModCollector<'_, '_> { Ok(()) } - fn collect_macro_rules(&mut self, id: FileItemTreeId, module: ModuleId) { + fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); @@ -2402,7 +2391,7 @@ impl ModCollector<'_, '_> { ); } - fn collect_macro_def(&mut self, id: FileItemTreeId, module: ModuleId) { + fn collect_macro_def(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); From 80996dca35454956a5de5a9ae36c461772343cf8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 10:25:21 +0200 Subject: [PATCH 03/14] `AttrOwner` needs no `ModItem` --- crates/hir-def/src/attr.rs | 4 +-- crates/hir-def/src/db.rs | 4 +-- crates/hir-def/src/item_tree.rs | 32 +++++++++--------- crates/hir-def/src/nameres/collector.rs | 43 +++++++++---------------- 4 files changed, 36 insertions(+), 47 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index e1bf6fde8a..08986d68e5 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -526,7 +526,7 @@ impl AttrsWithOwner { ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(declaration.into())) + .raw_attrs(AttrOwner::Item(declaration.erase())) .clone(); let tree = db.file_item_tree(definition.into()); let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); @@ -538,7 +538,7 @@ impl AttrsWithOwner { } ModuleOrigin::Inline { definition_tree_id, definition } => definition_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(definition.into())) + .raw_attrs(AttrOwner::Item(definition.erase())) .clone(), ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 362c0daa9b..95e33dde58 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -24,7 +24,7 @@ use crate::{ }, hir::generics::GenericParams, import_map::ImportMap, - item_tree::{AttrOwner, ItemTree}, + item_tree::ItemTree, lang_item::{self, LangItem}, nameres::{ assoc::{ImplItems, TraitItems}, @@ -376,7 +376,7 @@ fn include_macro_invoc( fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { let file = crate_id.data(db).root_file_id(db); let item_tree = db.file_item_tree(file.into()); - let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); + let attrs = item_tree.raw_attrs(crate::item_tree::AttrOwner::TopLevel); for attr in &**attrs { match attr.path().as_ident() { Some(ident) if *ident == sym::no_std => return true, diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 578f5fdee2..4b3890ae96 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -51,10 +51,10 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::{Arena, Idx}; +use la_arena::Idx; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; +use span::{AstIdNode, Edition, ErasedFileAstId, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; use triomphe::Arc; @@ -90,6 +90,7 @@ impl fmt::Debug for RawVisibilityId { #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { top_level: SmallVec<[ModItem; 1]>, + // Consider splitting this into top level RawAttrs and the map? attrs: FxHashMap, data: Option>, @@ -174,7 +175,7 @@ impl ItemTree { /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. - pub fn top_level_items(&self) -> &[ModItem] { + pub(crate) fn top_level_items(&self) -> &[ModItem] { &self.top_level } @@ -310,7 +311,7 @@ pub struct ItemTreeDataStats { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum AttrOwner { /// Attributes on an item. - ModItem(ModItem), + Item(ErasedFileAstId), /// Inner attributes of the source file. TopLevel, } @@ -318,7 +319,7 @@ pub enum AttrOwner { impl From for AttrOwner { #[inline] fn from(value: ModItem) -> Self { - AttrOwner::ModItem(value) + AttrOwner::Item(value.ast_id().erase()) } } @@ -365,25 +366,25 @@ impl TreeId { } macro_rules! mod_items { - ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { + ($mod_item:ident -> $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] - pub enum ModItem { + pub(crate) enum $mod_item { $( $typ(FileAstId<$ast>), )+ } - impl ModItem { - pub fn ast_id(self) -> FileAstId { + impl $mod_item { + pub(crate) fn ast_id(self) -> FileAstId { match self { - $(ModItem::$typ(it) => it.upcast()),+ + $($mod_item::$typ(it) => it.upcast()),+ } } } $( - impl From> for ModItem { - fn from(id: FileAstId<$ast>) -> ModItem { + impl From> for $mod_item { + fn from(id: FileAstId<$ast>) -> $mod_item { ModItem::$typ(id) } } @@ -414,6 +415,7 @@ macro_rules! mod_items { } mod_items! { +ModItem -> Use in uses -> ast::Use, ExternCrate in extern_crates -> ast::ExternCrate, ExternBlock in extern_blocks -> ast::ExternBlock, @@ -539,7 +541,7 @@ pub struct ExternCrate { #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { pub ast_id: FileAstId, - pub children: Box<[ModItem]>, + pub(crate) children: Box<[ModItem]>, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -647,12 +649,12 @@ pub struct TypeAlias { pub struct Mod { pub name: Name, pub visibility: RawVisibilityId, - pub kind: ModKind, + pub(crate) kind: ModKind, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] -pub enum ModKind { +pub(crate) enum ModKind { /// `mod m { ... }` Inline { items: Box<[ModItem]> }, /// `mod m;` diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index a8ee92d813..703cb79b55 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, - MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, + self, AttrOwner, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, + ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -246,7 +246,7 @@ struct DefCollector<'a> { /// This also stores the attributes to skip when we resolve derive helpers and non-macro /// non-builtin attributes in general. // FIXME: There has to be a better way to do this - skip_attrs: FxHashMap, AttrId>, + skip_attrs: FxHashMap>, AttrId>, } impl DefCollector<'_> { @@ -472,7 +472,7 @@ impl DefCollector<'_> { attr.path().clone(), )); - self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id); + self.skip_attrs.insert(ast_id.ast_id.with_value(mod_item.ast_id()), attr.id); Some((idx, directive, *mod_item, *tree)) } @@ -1371,7 +1371,9 @@ impl DefCollector<'_> { let mut recollect_without = |collector: &mut Self| { // Remove the original directive since we resolved it. let mod_dir = collector.mod_dirs[&directive.module_id].clone(); - collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); + collector + .skip_attrs + .insert(InFile::new(file_id, mod_item.ast_id()), attr.id); let item_tree = tree.item_tree(self.db); ModCollector { @@ -1728,25 +1730,7 @@ impl ModCollector<'_, '_> { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { - let ast_id = match item { - ModItem::Use(it) => self.item_tree[it].ast_id.erase(), - ModItem::ExternCrate(it) => self.item_tree[it].ast_id.erase(), - ModItem::ExternBlock(it) => self.item_tree[it].ast_id.erase(), - ModItem::Function(it) => self.item_tree[it].ast_id.erase(), - ModItem::Struct(it) => self.item_tree[it].ast_id.erase(), - ModItem::Union(it) => self.item_tree[it].ast_id.erase(), - ModItem::Enum(it) => self.item_tree[it].ast_id.erase(), - ModItem::Const(it) => self.item_tree[it].ast_id.erase(), - ModItem::Static(it) => self.item_tree[it].ast_id.erase(), - ModItem::Trait(it) => self.item_tree[it].ast_id.erase(), - ModItem::TraitAlias(it) => self.item_tree[it].ast_id.erase(), - ModItem::Impl(it) => self.item_tree[it].ast_id.erase(), - ModItem::TypeAlias(it) => self.item_tree[it].ast_id.erase(), - ModItem::Mod(it) => self.item_tree[it].ast_id.erase(), - ModItem::MacroCall(it) => self.item_tree[it].ast_id.erase(), - ModItem::MacroRules(it) => self.item_tree[it].ast_id.erase(), - ModItem::Macro2(it) => self.item_tree[it].ast_id.erase(), - }; + let ast_id = item.ast_id().erase(); self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg); return; } @@ -2256,8 +2240,11 @@ impl ModCollector<'_, '_> { mod_item: ModItem, container: ItemContainerId, ) -> Result<(), ()> { - let mut ignore_up_to = - self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied(); + let mut ignore_up_to = self + .def_collector + .skip_attrs + .get(&InFile::new(self.file_id(), mod_item.ast_id())) + .copied(); let iter = attrs .iter() .dedup_by(|a, b| { @@ -2309,7 +2296,7 @@ impl ModCollector<'_, '_> { fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); let export_attr = || attrs.by_key(sym::macro_export); @@ -2398,7 +2385,7 @@ impl ModCollector<'_, '_> { // Case 1: builtin macros let mut helpers_opt = None; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { if let Some(expander) = find_builtin_macro(&mac.name) { match expander { From 8930c58d30ab18711659719c949768657407b552 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:06:32 +0200 Subject: [PATCH 04/14] Coalesce item tree data maps --- crates/hir-def/src/item_tree.rs | 157 +++++++++--------------- crates/hir-def/src/item_tree/lower.rs | 63 ++++------ crates/hir-def/src/item_tree/pretty.rs | 41 ++++--- crates/hir-def/src/nameres/collector.rs | 58 ++++----- 4 files changed, 138 insertions(+), 181 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 4b3890ae96..b295767399 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -89,11 +89,12 @@ impl fmt::Debug for RawVisibilityId { /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { - top_level: SmallVec<[ModItem; 1]>, + top_level: SmallVec<[ModItemId; 1]>, // Consider splitting this into top level RawAttrs and the map? attrs: FxHashMap, - data: Option>, + vis: ItemVisibilities, + data: FxHashMap, ModItem>, } impl ItemTree { @@ -130,14 +131,15 @@ impl ItemTree { if let Some(attrs) = top_attrs { item_tree.attrs.insert(AttrOwner::TopLevel, attrs); } - if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() { EMPTY .get_or_init(|| { Arc::new(ItemTree { top_level: SmallVec::new_const(), attrs: FxHashMap::default(), - data: None, + data: FxHashMap::default(), + vis: ItemVisibilities { arena: Box::new([]) }, }) }) .clone() @@ -156,14 +158,15 @@ impl ItemTree { let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let mut item_tree = ctx.lower_block(&block); - if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() { EMPTY .get_or_init(|| { Arc::new(ItemTree { top_level: SmallVec::new_const(), attrs: FxHashMap::default(), - data: None, + data: FxHashMap::default(), + vis: ItemVisibilities { arena: Box::new([]) }, }) }) .clone() @@ -175,7 +178,7 @@ impl ItemTree { /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. - pub(crate) fn top_level_items(&self) -> &[ModItem] { + pub(crate) fn top_level_items(&self) -> &[ModItemId] { &self.top_level } @@ -200,74 +203,33 @@ impl ItemTree { /// /// For more detail, see [`ItemTreeDataStats`]. pub fn item_tree_stats(&self) -> ItemTreeDataStats { - match self.data { - Some(ref data) => ItemTreeDataStats { - traits: data.traits.len(), - impls: data.impls.len(), - mods: data.mods.len(), - macro_calls: data.macro_calls.len(), - macro_rules: data.macro_rules.len(), - }, - None => ItemTreeDataStats::default(), + let mut traits = 0; + let mut impls = 0; + let mut mods = 0; + let mut macro_calls = 0; + let mut macro_rules = 0; + for item in self.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, + _ => {} + } } + ItemTreeDataStats { traits, impls, mods, macro_calls, macro_rules } } pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String { pretty::print_item_tree(db, self, edition) } - fn data(&self) -> &ItemTreeData { - self.data.as_ref().expect("attempted to access data of empty ItemTree") - } - - fn data_mut(&mut self) -> &mut ItemTreeData { - self.data.get_or_insert_with(Box::default) - } - fn shrink_to_fit(&mut self) { - let ItemTree { top_level, attrs, data } = self; + let ItemTree { top_level, attrs, data, vis: _ } = self; top_level.shrink_to_fit(); attrs.shrink_to_fit(); - if let Some(data) = data { - let ItemTreeData { - uses, - extern_crates, - extern_blocks, - functions, - structs, - unions, - enums, - consts, - statics, - traits, - trait_aliases, - impls, - type_aliases, - mods, - macro_calls, - macro_rules, - macro_defs, - vis: _, - } = &mut **data; - - uses.shrink_to_fit(); - extern_crates.shrink_to_fit(); - extern_blocks.shrink_to_fit(); - functions.shrink_to_fit(); - structs.shrink_to_fit(); - unions.shrink_to_fit(); - enums.shrink_to_fit(); - consts.shrink_to_fit(); - statics.shrink_to_fit(); - traits.shrink_to_fit(); - trait_aliases.shrink_to_fit(); - impls.shrink_to_fit(); - type_aliases.shrink_to_fit(); - mods.shrink_to_fit(); - macro_calls.shrink_to_fit(); - macro_rules.shrink_to_fit(); - macro_defs.shrink_to_fit(); - } + data.shrink_to_fit(); } } @@ -276,29 +238,26 @@ struct ItemVisibilities { arena: Box<[RawVisibility]>, } -#[derive(Default, Debug, Eq, PartialEq)] -struct ItemTreeData { - uses: FxHashMap, Use>, - extern_crates: FxHashMap, ExternCrate>, - extern_blocks: FxHashMap, ExternBlock>, - functions: FxHashMap, Function>, - structs: FxHashMap, Struct>, - unions: FxHashMap, Union>, - enums: FxHashMap, Enum>, - consts: FxHashMap, Const>, - statics: FxHashMap, Static>, - traits: FxHashMap, Trait>, - trait_aliases: FxHashMap, TraitAlias>, - impls: FxHashMap, Impl>, - type_aliases: FxHashMap, TypeAlias>, - mods: FxHashMap, Mod>, - macro_calls: FxHashMap, MacroCall>, - macro_rules: FxHashMap, MacroRules>, - macro_defs: FxHashMap, Macro2>, - - vis: ItemVisibilities, +#[derive(Debug, Clone, Eq, PartialEq)] +enum ModItem { + Const(Const), + Enum(Enum), + ExternBlock(ExternBlock), + ExternCrate(ExternCrate), + Function(Function), + Impl(Impl), + Macro2(Macro2), + MacroCall(MacroCall), + MacroRules(MacroRules), + Mod(Mod), + Static(Static), + Struct(Struct), + Trait(Trait), + TraitAlias(TraitAlias), + TypeAlias(TypeAlias), + Union(Union), + Use(Use), } - #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { pub traits: usize, @@ -316,9 +275,9 @@ pub enum AttrOwner { TopLevel, } -impl From for AttrOwner { +impl From for AttrOwner { #[inline] - fn from(value: ModItem) -> Self { + fn from(value: ModItemId) -> Self { AttrOwner::Item(value.ast_id().erase()) } } @@ -385,7 +344,7 @@ macro_rules! mod_items { $( impl From> for $mod_item { fn from(id: FileAstId<$ast>) -> $mod_item { - ModItem::$typ(id) + ModItemId::$typ(id) } } )+ @@ -399,7 +358,10 @@ macro_rules! mod_items { } fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self { - &tree.data().$fld[&index] + match &tree.data[&index.upcast()] { + ModItem::$typ(item) => item, + _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), + } } } @@ -407,7 +369,10 @@ macro_rules! mod_items { type Output = $typ; fn index(&self, index: FileAstId<$ast>) -> &Self::Output { - &self.data().$fld[&index] + match &self.data[&index.upcast()] { + ModItem::$typ(item) => item, + _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), + } } } )+ @@ -415,7 +380,7 @@ macro_rules! mod_items { } mod_items! { -ModItem -> +ModItemId -> Use in uses -> ast::Use, ExternCrate in extern_crates -> ast::ExternCrate, ExternBlock in extern_blocks -> ast::ExternBlock, @@ -463,7 +428,7 @@ impl Index for ItemTree { VisibilityExplicitness::Explicit, ) }), - _ => &self.data().vis.arena[index.0 as usize], + _ => &self.vis.arena[index.0 as usize], } } } @@ -541,7 +506,7 @@ pub struct ExternCrate { #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { pub ast_id: FileAstId, - pub(crate) children: Box<[ModItem]>, + pub(crate) children: Box<[ModItemId]>, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -656,7 +621,7 @@ pub struct Mod { #[derive(Debug, Clone, Eq, PartialEq)] pub(crate) enum ModKind { /// `mod m { ... }` - Inline { items: Box<[ModItem]> }, + Inline { items: Box<[ModItemId]> }, /// `mod m;` Outline, } diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 17b115b6ec..f3e71effe4 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -21,10 +21,9 @@ use crate::{ db::DefDatabase, item_tree::{ AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, - Interned, ItemTree, ItemTreeAstId, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, - ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, - StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, - VisibilityExplicitness, + 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, }, }; @@ -56,9 +55,7 @@ impl<'a> Ctx<'a> { pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree { self.tree.top_level = item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); - if let Some(data) = &mut self.tree.data { - data.vis.arena = self.visibilities.into_iter().collect(); - } + self.tree.vis.arena = self.visibilities.into_iter().collect(); self.tree } @@ -92,9 +89,7 @@ impl<'a> Ctx<'a> { } } - if let Some(data) = &mut self.tree.data { - data.vis.arena = self.visibilities.into_iter().collect(); - } + self.tree.vis.arena = self.visibilities.into_iter().collect(); self.tree } @@ -120,18 +115,12 @@ impl<'a> Ctx<'a> { } } } - if let Some(data) = &mut self.tree.data { - data.vis.arena = self.visibilities.into_iter().collect(); - } + self.tree.vis.arena = self.visibilities.into_iter().collect(); self.tree } - fn data(&mut self) -> &mut ItemTreeData { - self.tree.data_mut() - } - - fn lower_mod_item(&mut self, item: &ast::Item) -> Option { - let mod_item: ModItem = match item { + fn lower_mod_item(&mut self, item: &ast::Item) -> Option { + let mod_item: ModItemId = match item { ast::Item::Struct(ast) => self.lower_struct(ast)?.into(), ast::Item::Union(ast) => self.lower_union(ast)?.into(), ast::Item::Enum(ast) => self.lower_enum(ast)?.into(), @@ -175,7 +164,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.data().structs.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Struct(res)); Some(ast_id) } @@ -185,7 +174,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.data().unions.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Union(res)); Some(ast_id) } @@ -194,7 +183,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.data().enums.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Enum(res)); Some(ast_id) } @@ -206,7 +195,7 @@ impl<'a> Ctx<'a> { let res = Function { name, visibility, ast_id }; - self.data().functions.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Function(res)); Some(ast_id) } @@ -218,7 +207,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.data().type_aliases.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::TypeAlias(res)); Some(ast_id) } @@ -227,7 +216,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.data().statics.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Static(res)); Some(ast_id) } @@ -236,7 +225,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.data().consts.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Const(res)); ast_id } @@ -258,7 +247,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.data().mods.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Mod(res)); Some(ast_id) } @@ -268,7 +257,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.data().traits.insert(ast_id, def); + self.tree.data.insert(ast_id.upcast(), ModItem::Trait(def)); Some(ast_id) } @@ -281,7 +270,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.data().trait_aliases.insert(ast_id, alias); + self.tree.data.insert(ast_id.upcast(), ModItem::TraitAlias(alias)); Some(ast_id) } @@ -290,7 +279,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.data().impls.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Impl(res)); ast_id } @@ -302,7 +291,7 @@ impl<'a> Ctx<'a> { })?; let res = Use { visibility, ast_id, use_tree }; - self.data().uses.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Use(res)); Some(ast_id) } @@ -318,7 +307,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.data().extern_crates.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::ExternCrate(res)); Some(ast_id) } @@ -332,7 +321,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.data().macro_calls.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::MacroCall(res)); Some(ast_id) } @@ -341,7 +330,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.data().macro_rules.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::MacroRules(res)); Some(ast_id) } @@ -352,7 +341,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(m); let res = Macro2 { name: name.as_name(), ast_id, visibility }; - self.data().macro_defs.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Macro2(res)); Some(ast_id) } @@ -365,7 +354,7 @@ impl<'a> Ctx<'a> { // (in other words, the knowledge that they're in an extern block must not be used). // This is because an extern block can contain macros whose ItemTree's top-level items // should be considered to be in an extern block too. - let mod_item: ModItem = match &item { + let mod_item: ModItemId = match &item { ast::ExternItem::Fn(ast) => self.lower_function(ast)?.into(), ast::ExternItem::Static(ast) => self.lower_static(ast)?.into(), ast::ExternItem::TypeAlias(ty) => self.lower_type_alias(ty)?.into(), @@ -379,7 +368,7 @@ impl<'a> Ctx<'a> { }); let res = ExternBlock { ast_id, children }; - self.data().extern_blocks.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::ExternBlock(res)); ast_id } diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 0c62b86dae..9a5ca73836 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -7,8 +7,9 @@ use span::{Edition, ErasedFileAstId}; use crate::{ item_tree::{ AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, - ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, RawAttrs, RawVisibilityId, - Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, + ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, + RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, + UseTreeKind, }, visibility::RawVisibility, }; @@ -159,11 +160,11 @@ impl Printer<'_> { } } - fn print_mod_item(&mut self, item: ModItem) { + fn print_mod_item(&mut self, item: ModItemId) { self.print_attrs_of(item, "\n"); match item { - ModItem::Use(it) => { + ModItemId::Use(it) => { let Use { visibility, use_tree, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -171,7 +172,7 @@ impl Printer<'_> { self.print_use_tree(use_tree); wln!(self, ";"); } - ModItem::ExternCrate(it) => { + ModItemId::ExternCrate(it) => { let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -181,7 +182,7 @@ impl Printer<'_> { } wln!(self, ";"); } - ModItem::ExternBlock(it) => { + ModItemId::ExternBlock(it) => { let ExternBlock { ast_id, children } = &self.tree[it]; self.print_ast_id(ast_id.erase()); w!(self, "extern {{"); @@ -192,13 +193,13 @@ impl Printer<'_> { }); wln!(self, "}}"); } - ModItem::Function(it) => { + ModItemId::Function(it) => { let Function { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "fn {};", name.display(self.db, self.edition)); } - ModItem::Struct(it) => { + ModItemId::Struct(it) => { let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -210,7 +211,7 @@ impl Printer<'_> { wln!(self, ";"); } } - ModItem::Union(it) => { + ModItemId::Union(it) => { let Union { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -218,13 +219,13 @@ impl Printer<'_> { self.print_fields(FieldsShape::Record); wln!(self); } - ModItem::Enum(it) => { + ModItemId::Enum(it) => { let Enum { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition)); } - ModItem::Const(it) => { + ModItemId::Const(it) => { let Const { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -235,7 +236,7 @@ impl Printer<'_> { } wln!(self, " = _;"); } - ModItem::Static(it) => { + ModItemId::Static(it) => { let Static { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -244,24 +245,24 @@ impl Printer<'_> { w!(self, " = _;"); wln!(self); } - ModItem::Trait(it) => { + ModItemId::Trait(it) => { let Trait { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition)); } - ModItem::TraitAlias(it) => { + ModItemId::TraitAlias(it) => { let TraitAlias { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); } - ModItem::Impl(it) => { + ModItemId::Impl(it) => { let Impl { ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); w!(self, "impl {{ ... }}"); } - ModItem::TypeAlias(it) => { + ModItemId::TypeAlias(it) => { let TypeAlias { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -269,7 +270,7 @@ impl Printer<'_> { w!(self, ";"); wln!(self); } - ModItem::Mod(it) => { + ModItemId::Mod(it) => { let Mod { name, visibility, kind, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -289,7 +290,7 @@ impl Printer<'_> { } } } - ModItem::MacroCall(it) => { + ModItemId::MacroCall(it) => { let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; let _ = writeln!( self, @@ -300,12 +301,12 @@ impl Printer<'_> { ); wln!(self, "{}!(...);", path.display(self.db, self.edition)); } - ModItem::MacroRules(it) => { + ModItemId::MacroRules(it) => { let MacroRules { name, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db, self.edition)); } - ModItem::Macro2(it) => { + ModItemId::Macro2(it) => { let Macro2 { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 703cb79b55..3dc76dcb8f 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -36,7 +36,7 @@ use crate::{ item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ self, AttrOwner, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, - ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, + ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -208,7 +208,7 @@ enum MacroDirectiveKind { Attr { ast_id: AstIdWithPath, attr: Attr, - mod_item: ModItem, + mod_item: ModItemId, /* is this needed? */ tree: TreeId, }, } @@ -1436,9 +1436,9 @@ impl DefCollector<'_> { let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { - ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(), - ModItem::Union(union) => item_tree[union].ast_id().upcast(), - ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(), + ModItemId::Struct(strukt) => item_tree[strukt].ast_id().upcast(), + ModItemId::Union(union) => item_tree[union].ast_id().upcast(), + ModItemId::Enum(enum_) => item_tree[enum_].ast_id().upcast(), _ => { let diag = DefDiagnostic::invalid_derive_target( directive.module_id, @@ -1682,12 +1682,12 @@ struct ModCollector<'a, 'b> { } impl ModCollector<'_, '_> { - fn collect_in_top_module(&mut self, items: &[ModItem]) { + fn collect_in_top_module(&mut self, items: &[ModItemId]) { let module = self.def_collector.def_map.module_id(self.module_id); self.collect(items, module.into()) } - fn collect(&mut self, items: &[ModItem], container: ItemContainerId) { + fn collect(&mut self, items: &[ModItemId], container: ItemContainerId) { let krate = self.def_collector.def_map.krate; let is_crate_root = self.module_id == DefMap::ROOT && self.def_collector.def_map.block.is_none(); @@ -1726,7 +1726,7 @@ impl ModCollector<'_, '_> { .unwrap_or(Visibility::Public) }; - let mut process_mod_item = |item: ModItem| { + let mut process_mod_item = |item: ModItemId| { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { @@ -1748,8 +1748,8 @@ impl ModCollector<'_, '_> { self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map); match item { - ModItem::Mod(m) => self.collect_module(m, &attrs), - ModItem::Use(item_tree_id) => { + ModItemId::Mod(m) => self.collect_module(m, &attrs), + ModItemId::Use(item_tree_id) => { let id = UseLoc { container: module, id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id), @@ -1771,7 +1771,7 @@ impl ModCollector<'_, '_> { }, ) } - ModItem::ExternCrate(item_tree_id) => { + ModItemId::ExternCrate(item_tree_id) => { let item_tree::ExternCrate { name, visibility, alias, ast_id } = &self.item_tree[item_tree_id]; @@ -1845,7 +1845,7 @@ impl ModCollector<'_, '_> { ); } } - ModItem::ExternBlock(block) => { + ModItemId::ExternBlock(block) => { let extern_block_id = ExternBlockLoc { container: module, id: InFile::new(self.file_id(), self.item_tree[block].ast_id), @@ -1859,10 +1859,12 @@ impl ModCollector<'_, '_> { ItemContainerId::ExternBlockId(extern_block_id), ) } - ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container), - ModItem::MacroRules(id) => self.collect_macro_rules(id, module), - ModItem::Macro2(id) => self.collect_macro_def(id, module), - ModItem::Impl(imp) => { + ModItemId::MacroCall(mac) => { + self.collect_macro_call(&self.item_tree[mac], container) + } + ModItemId::MacroRules(id) => self.collect_macro_rules(id, module), + ModItemId::Macro2(id) => self.collect_macro_def(id, module), + ModItemId::Impl(imp) => { let impl_id = ImplLoc { container: module, id: InFile::new(self.file_id(), self.item_tree[imp].ast_id), @@ -1870,7 +1872,7 @@ impl ModCollector<'_, '_> { .intern(db); self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) } - ModItem::Function(id) => { + ModItemId::Function(id) => { let it = &self.item_tree[id]; let fn_id = FunctionLoc { container, @@ -1895,7 +1897,7 @@ impl ModCollector<'_, '_> { update_def(self.def_collector, fn_id.into(), &it.name, vis, false); } - ModItem::Struct(id) => { + ModItemId::Struct(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1909,7 +1911,7 @@ impl ModCollector<'_, '_> { !matches!(it.shape, FieldsShape::Record), ); } - ModItem::Union(id) => { + ModItemId::Union(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1923,7 +1925,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::Enum(id) => { + ModItemId::Enum(id) => { let it = &self.item_tree[id]; let enum_ = EnumLoc { container: module, @@ -1934,7 +1936,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); } - ModItem::Const(id) => { + ModItemId::Const(id) => { let it = &self.item_tree[id]; let const_id = ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) } @@ -1954,7 +1956,7 @@ impl ModCollector<'_, '_> { } } } - ModItem::Static(id) => { + ModItemId::Static(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1968,7 +1970,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::Trait(id) => { + ModItemId::Trait(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1982,7 +1984,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::TraitAlias(id) => { + ModItemId::TraitAlias(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1999,7 +2001,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::TypeAlias(id) => { + ModItemId::TypeAlias(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -2022,12 +2024,12 @@ impl ModCollector<'_, '_> { if is_crate_root { items .iter() - .filter(|it| matches!(it, ModItem::ExternCrate(..))) + .filter(|it| matches!(it, ModItemId::ExternCrate(..))) .copied() .for_each(&mut process_mod_item); items .iter() - .filter(|it| !matches!(it, ModItem::ExternCrate(..))) + .filter(|it| !matches!(it, ModItemId::ExternCrate(..))) .copied() .for_each(process_mod_item); } else { @@ -2237,7 +2239,7 @@ impl ModCollector<'_, '_> { fn resolve_attributes( &mut self, attrs: &Attrs, - mod_item: ModItem, + mod_item: ModItemId, container: ItemContainerId, ) -> Result<(), ()> { let mut ignore_up_to = self From f27268f319d402fcd68509e1836edaea8dc357ea Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:25:20 +0200 Subject: [PATCH 05/14] Ditch the unnecessary smallvec --- crates/hir-def/src/item_tree.rs | 11 +++++------ crates/hir-def/src/item_tree/lower.rs | 16 ++++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index b295767399..9f8d7b9e31 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -53,7 +53,6 @@ use hir_expand::{ use intern::Interned; use la_arena::Idx; use rustc_hash::FxHashMap; -use smallvec::SmallVec; use span::{AstIdNode, Edition, ErasedFileAstId, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; @@ -89,11 +88,12 @@ impl fmt::Debug for RawVisibilityId { /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { - top_level: SmallVec<[ModItemId; 1]>, + top_level: Box<[ModItemId]>, // Consider splitting this into top level RawAttrs and the map? attrs: FxHashMap, vis: ItemVisibilities, + // FIXME: They values store the key, turn this into a FxHashSet instead? data: FxHashMap, ModItem>, } @@ -136,7 +136,7 @@ impl ItemTree { EMPTY .get_or_init(|| { Arc::new(ItemTree { - top_level: SmallVec::new_const(), + top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), vis: ItemVisibilities { arena: Box::new([]) }, @@ -163,7 +163,7 @@ impl ItemTree { EMPTY .get_or_init(|| { Arc::new(ItemTree { - top_level: SmallVec::new_const(), + top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), vis: ItemVisibilities { arena: Box::new([]) }, @@ -226,8 +226,7 @@ impl ItemTree { } fn shrink_to_fit(&mut self) { - let ItemTree { top_level, attrs, data, vis: _ } = self; - top_level.shrink_to_fit(); + let ItemTree { top_level: _, attrs, data, vis: _ } = self; attrs.shrink_to_fit(); data.shrink_to_fit(); } diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index f3e71effe4..a7038356b3 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -33,6 +33,7 @@ pub(super) struct Ctx<'a> { source_ast_id_map: Arc, span_map: OnceCell, file: HirFileId, + top_level: Vec, visibilities: FxIndexSet, } @@ -45,6 +46,7 @@ impl<'a> Ctx<'a> { file, span_map: OnceCell::new(), visibilities: FxIndexSet::default(), + top_level: Vec::new(), } } @@ -53,14 +55,14 @@ impl<'a> Ctx<'a> { } pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree { - self.tree.top_level = - item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); + self.top_level = item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); self.tree.vis.arena = self.visibilities.into_iter().collect(); + self.tree.top_level = self.top_level.into_boxed_slice(); self.tree } pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree { - self.tree.top_level = stmts + self.top_level = stmts .statements() .filter_map(|stmt| { match stmt { @@ -84,18 +86,19 @@ impl<'a> Ctx<'a> { if let Some(call) = tail_macro.macro_call() { cov_mark::hit!(macro_stmt_with_trailing_macro_expr); if let Some(mod_item) = self.lower_mod_item(&call.into()) { - self.tree.top_level.push(mod_item); + self.top_level.push(mod_item); } } } self.tree.vis.arena = self.visibilities.into_iter().collect(); + self.tree.top_level = self.top_level.into_boxed_slice(); self.tree } pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree { self.tree.attrs.insert(AttrOwner::TopLevel, RawAttrs::new(self.db, block, self.span_map())); - self.tree.top_level = block + self.top_level = block .statements() .filter_map(|stmt| match stmt { ast::Stmt::Item(item) => self.lower_mod_item(&item), @@ -111,11 +114,12 @@ impl<'a> Ctx<'a> { if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() { if let Some(call) = expr.macro_call() { if let Some(mod_item) = self.lower_mod_item(&call.into()) { - self.tree.top_level.push(mod_item); + self.top_level.push(mod_item); } } } self.tree.vis.arena = self.visibilities.into_iter().collect(); + self.tree.top_level = self.top_level.into_boxed_slice(); self.tree } From 83a7ecdeada09d26247189e304ab34e1fd30848d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:41:46 +0200 Subject: [PATCH 06/14] Remove `AttrOwner` --- crates/hir-def/src/attr.rs | 16 +++--- crates/hir-def/src/db.rs | 2 +- crates/hir-def/src/item_tree.rs | 68 ++++++++++++------------- crates/hir-def/src/item_tree/lower.rs | 18 +++---- crates/hir-def/src/item_tree/pretty.rs | 15 +++--- crates/hir-def/src/nameres/collector.rs | 10 ++-- 6 files changed, 60 insertions(+), 69 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 08986d68e5..d63bd391fd 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -26,7 +26,6 @@ use crate::{ AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, VariantId, db::DefDatabase, - item_tree::AttrOwner, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, @@ -526,23 +525,22 @@ impl AttrsWithOwner { ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::Item(declaration.erase())) + .raw_attrs(declaration.upcast()) .clone(); let tree = db.file_item_tree(definition.into()); - let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); + let def_attrs = tree.top_level_raw_attrs().clone(); decl_attrs.merge(def_attrs) } ModuleOrigin::CrateRoot { definition } => { let tree = db.file_item_tree(definition.into()); - tree.raw_attrs(AttrOwner::TopLevel).clone() + tree.top_level_raw_attrs().clone() + } + ModuleOrigin::Inline { definition_tree_id, definition } => { + definition_tree_id.item_tree(db).raw_attrs(definition.upcast()).clone() } - ModuleOrigin::Inline { definition_tree_id, definition } => definition_tree_id - .item_tree(db) - .raw_attrs(AttrOwner::Item(definition.erase())) - .clone(), ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); - tree.raw_attrs(AttrOwner::TopLevel).clone() + tree.top_level_raw_attrs().clone() } }; Attrs::expand_cfg_attr(db, module.krate, raw_attrs) diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 95e33dde58..5f99693139 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -376,7 +376,7 @@ fn include_macro_invoc( fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { let file = crate_id.data(db).root_file_id(db); let item_tree = db.file_item_tree(file.into()); - let attrs = item_tree.raw_attrs(crate::item_tree::AttrOwner::TopLevel); + let attrs = item_tree.top_level_raw_attrs(); for attr in &**attrs { match attr.path().as_ident() { Some(ident) if *ident == sym::no_std => return true, diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 9f8d7b9e31..79f4b174e1 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -53,7 +53,7 @@ use hir_expand::{ use intern::Interned; use la_arena::Idx; use rustc_hash::FxHashMap; -use span::{AstIdNode, Edition, ErasedFileAstId, FileAstId, SyntaxContext}; +use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; use triomphe::Arc; @@ -89,9 +89,8 @@ impl fmt::Debug for RawVisibilityId { #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { top_level: Box<[ModItemId]>, - // Consider splitting this into top level RawAttrs and the map? - attrs: FxHashMap, - + top_attrs: RawAttrs, + attrs: FxHashMap, RawAttrs>, vis: ItemVisibilities, // FIXME: They values store the key, turn this into a FxHashSet instead? data: FxHashMap, ModItem>, @@ -104,12 +103,13 @@ impl ItemTree { let ctx = lower::Ctx::new(db, file_id); let syntax = db.parse_or_expand(file_id); - let mut top_attrs = None; let mut item_tree = match_ast! { match syntax { ast::SourceFile(file) => { - top_attrs = Some(RawAttrs::new(db, &file, ctx.span_map())); - ctx.lower_module_items(&file) + let top_attrs = RawAttrs::new(db, &file, ctx.span_map()); + let mut item_tree = ctx.lower_module_items(&file); + item_tree.top_attrs = top_attrs; + item_tree }, ast::MacroItems(items) => { ctx.lower_module_items(&items) @@ -128,10 +128,10 @@ impl ItemTree { } }; - if let Some(attrs) = top_attrs { - item_tree.attrs.insert(AttrOwner::TopLevel, attrs); - } - if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() + && item_tree.top_level.is_empty() + && item_tree.attrs.is_empty() + && item_tree.top_attrs.is_empty() { EMPTY .get_or_init(|| { @@ -139,6 +139,7 @@ impl ItemTree { top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, vis: ItemVisibilities { arena: Box::new([]) }, }) }) @@ -158,7 +159,10 @@ impl ItemTree { 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() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() + && item_tree.top_level.is_empty() + && item_tree.attrs.is_empty() + && item_tree.top_attrs.is_empty() { EMPTY .get_or_init(|| { @@ -166,6 +170,7 @@ impl ItemTree { top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, vis: ItemVisibilities { arena: Box::new([]) }, }) }) @@ -183,19 +188,25 @@ impl ItemTree { } /// Returns the inner attributes of the source file. - pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { - Attrs::expand_cfg_attr( - db, - krate, - self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(), - ) + pub fn top_level_raw_attrs(&self) -> &RawAttrs { + &self.top_attrs } - pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs { + /// Returns the inner attributes of the source file. + pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { + Attrs::expand_cfg_attr(db, krate, self.top_attrs.clone()) + } + + pub(crate) fn raw_attrs(&self, of: FileAstId) -> &RawAttrs { self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY) } - pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs { + pub(crate) fn attrs( + &self, + db: &dyn DefDatabase, + krate: Crate, + of: FileAstId, + ) -> Attrs { Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone()) } @@ -226,7 +237,7 @@ impl ItemTree { } fn shrink_to_fit(&mut self) { - let ItemTree { top_level: _, attrs, data, vis: _ } = self; + let ItemTree { top_level: _, attrs, data, vis: _, top_attrs: _ } = self; attrs.shrink_to_fit(); data.shrink_to_fit(); } @@ -266,21 +277,6 @@ pub struct ItemTreeDataStats { pub macro_rules: usize, } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum AttrOwner { - /// Attributes on an item. - Item(ErasedFileAstId), - /// Inner attributes of the source file. - TopLevel, -} - -impl From for AttrOwner { - #[inline] - fn from(value: ModItemId) -> Self { - AttrOwner::Item(value.ast_id().erase()) - } -} - /// Trait implemented by all nodes in the item tree. pub trait ItemTreeNode: Clone { type Source: AstIdNode; diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index a7038356b3..c3089eef90 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -10,7 +10,7 @@ use hir_expand::{ span_map::{SpanMap, SpanMapRef}, }; use la_arena::Arena; -use span::{AstIdMap, SyntaxContext}; +use span::{AstIdMap, FileAstId, SyntaxContext}; use syntax::{ AstNode, ast::{self, HasModuleItem, HasName}, @@ -20,10 +20,10 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - AttrOwner, 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, + 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, }, }; @@ -97,7 +97,7 @@ impl<'a> Ctx<'a> { } pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree { - self.tree.attrs.insert(AttrOwner::TopLevel, RawAttrs::new(self.db, block, self.span_map())); + self.tree.top_attrs = RawAttrs::new(self.db, block, self.span_map()); self.top_level = block .statements() .filter_map(|stmt| match stmt { @@ -144,12 +144,12 @@ impl<'a> Ctx<'a> { ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(), }; let attrs = RawAttrs::new(self.db, item, self.span_map()); - self.add_attrs(mod_item.into(), attrs); + self.add_attrs(mod_item.ast_id(), attrs); Some(mod_item) } - fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) { + fn add_attrs(&mut self, item: FileAstId, attrs: RawAttrs) { if !attrs.is_empty() { match self.tree.attrs.entry(item) { Entry::Occupied(mut entry) => { @@ -365,7 +365,7 @@ impl<'a> Ctx<'a> { ast::ExternItem::MacroCall(call) => self.lower_macro_call(call)?.into(), }; let attrs = RawAttrs::new(self.db, &item, self.span_map()); - self.add_attrs(mod_item.into(), attrs); + self.add_attrs(mod_item.ast_id(), attrs); Some(mod_item) }) .collect() diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 9a5ca73836..11b9156898 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -6,10 +6,9 @@ use span::{Edition, ErasedFileAstId}; use crate::{ item_tree::{ - AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, - ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, - RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, - UseTreeKind, + Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ItemTree, + Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, RawVisibilityId, Static, + Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, }, visibility::RawVisibility, }; @@ -18,9 +17,7 @@ pub(super) fn print_item_tree(db: &dyn DefDatabase, tree: &ItemTree, edition: Ed let mut p = Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true, edition }; - if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) { - p.print_attrs(attrs, true, "\n"); - } + p.print_attrs(&tree.top_attrs, true, "\n"); p.blank(); for item in tree.top_level_items() { @@ -102,8 +99,8 @@ impl Printer<'_> { } } - fn print_attrs_of(&mut self, of: impl Into, separated_by: &str) { - if let Some(attrs) = self.tree.attrs.get(&of.into()) { + fn print_attrs_of(&mut self, of: ModItemId, separated_by: &str) { + if let Some(attrs) = self.tree.attrs.get(&of.ast_id()) { self.print_attrs(attrs, false, separated_by); } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 3dc76dcb8f..a6be3f1fbf 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, AttrOwner, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, - ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, + self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, + MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -1727,7 +1727,7 @@ impl ModCollector<'_, '_> { }; let mut process_mod_item = |item: ModItemId| { - let attrs = self.item_tree.attrs(db, krate, item.into()); + let attrs = self.item_tree.attrs(db, krate, item.ast_id()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { let ast_id = item.ast_id().erase(); @@ -2298,7 +2298,7 @@ impl ModCollector<'_, '_> { fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); let export_attr = || attrs.by_key(sym::macro_export); @@ -2387,7 +2387,7 @@ impl ModCollector<'_, '_> { // Case 1: builtin macros let mut helpers_opt = None; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { if let Some(expander) = find_builtin_macro(&mac.name) { match expander { From 23eef0c4eac5229d771fc676091e802ee05f9802 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:51:33 +0200 Subject: [PATCH 07/14] Shrink `ModItem` by usize --- crates/hir-def/src/item_tree.rs | 30 ++++++++++++++++++------- crates/hir-def/src/item_tree/lower.rs | 25 +++++++++------------ crates/hir-def/src/nameres/collector.rs | 2 +- crates/intern/src/symbol.rs | 1 + 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 79f4b174e1..2a277e4c54 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -51,7 +51,7 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::Idx; +use la_arena::{Idx, RawIdx}; use rustc_hash::FxHashMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; @@ -437,10 +437,10 @@ pub struct Use { #[derive(Debug, Clone, Eq, PartialEq)] pub struct UseTree { - pub index: Idx, kind: UseTreeKind, } +// FIXME: Would be nice to encode `None` into this #[derive(Debug, Clone, PartialEq, Eq)] pub enum ImportAlias { /// Unnamed alias, as in `use Foo as _;` @@ -655,15 +655,17 @@ pub enum ImportKind { TypeOnly, } -impl UseTree { +impl Use { /// Expands the `UseTree` into individually imported `ModPath`s. pub fn expand( &self, mut cb: impl FnMut(Idx, ModPath, ImportKind, Option), ) { - self.expand_impl(None, &mut cb) + self.use_tree.expand_impl(None, &mut 0, &mut cb) } +} +impl UseTree { /// The [`UseTreeKind`] of this `UseTree`. pub fn kind(&self) -> &UseTreeKind { &self.kind @@ -672,6 +674,7 @@ impl UseTree { fn expand_impl( &self, prefix: Option, + counting_index: &mut u32, cb: &mut impl FnMut(Idx, ModPath, ImportKind, Option), ) { fn concat_mod_paths( @@ -707,17 +710,27 @@ impl UseTree { match &self.kind { UseTreeKind::Single { path, alias } => { if let Some((path, kind)) = concat_mod_paths(prefix, path) { - cb(self.index, path, kind, alias.clone()); + cb(Idx::from_raw(RawIdx::from_u32(*counting_index)), path, kind, alias.clone()); } } UseTreeKind::Glob { path: Some(path) } => { if let Some((path, _)) = concat_mod_paths(prefix, path) { - cb(self.index, path, ImportKind::Glob, None); + cb( + Idx::from_raw(RawIdx::from_u32(*counting_index)), + path, + ImportKind::Glob, + None, + ); } } UseTreeKind::Glob { path: None } => { if let Some(prefix) = prefix { - cb(self.index, prefix, ImportKind::Glob, None); + cb( + Idx::from_raw(RawIdx::from_u32(*counting_index)), + prefix, + ImportKind::Glob, + None, + ); } } UseTreeKind::Prefixed { prefix: additional_prefix, list } => { @@ -729,7 +742,8 @@ impl UseTree { None => prefix, }; for tree in &**list { - tree.expand_impl(prefix.clone(), cb); + *counting_index += 1; + tree.expand_impl(prefix.clone(), counting_index, cb); } } } diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index c3089eef90..ab60b7ad70 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -424,17 +424,15 @@ impl UseTreeLowering<'_> { } }; + self.mapping.alloc(tree.clone()); let list = use_tree_list .use_trees() .filter_map(|tree| self.lower_use_tree(tree, span_for_range)) .collect(); - Some( - self.use_tree( - UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list }, - tree, - ), - ) + Some(UseTree { + kind: UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list }, + }) } else { let is_glob = tree.star_token().is_some(); let path = match tree.path() { @@ -453,23 +451,20 @@ impl UseTreeLowering<'_> { if path.is_none() { cov_mark::hit!(glob_enum_group); } - Some(self.use_tree(UseTreeKind::Glob { path: path.map(Interned::new) }, tree)) + self.mapping.alloc(tree.clone()); + Some(UseTree { kind: UseTreeKind::Glob { path: path.map(Interned::new) } }) } // Globs can't be renamed (_, Some(_), true) | (None, None, false) => None, // `bla::{ as Name}` is invalid (None, Some(_), false) => None, - (Some(path), alias, false) => Some( - self.use_tree(UseTreeKind::Single { path: Interned::new(path), alias }, tree), - ), + (Some(path), alias, false) => { + self.mapping.alloc(tree.clone()); + Some(UseTree { kind: UseTreeKind::Single { path: Interned::new(path), alias } }) + } } } } - - fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree { - let index = self.mapping.alloc(ast); - UseTree { index, kind } - } } pub(crate) fn lower_use_tree( diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index a6be3f1fbf..9801875ee4 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -163,7 +163,7 @@ impl Import { ) { let it = &tree[item]; let visibility = &tree[it.visibility]; - it.use_tree.expand(|idx, path, kind, alias| { + it.expand(|idx, path, kind, alias| { cb(Self { path, alias, diff --git a/crates/intern/src/symbol.rs b/crates/intern/src/symbol.rs index 8b2d6e8717..3b962a86f1 100644 --- a/crates/intern/src/symbol.rs +++ b/crates/intern/src/symbol.rs @@ -112,6 +112,7 @@ impl TaggedArcPtr { } } +// FIXME: This should have more than one niche #[derive(PartialEq, Eq, Hash)] pub struct Symbol { repr: TaggedArcPtr, From 2448abdb558a88b86234d746470bac9d67f2fde2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 12:02:53 +0200 Subject: [PATCH 08/14] Remove dead code --- crates/hir-def/src/item_tree.rs | 70 ++++++++++--------------- crates/hir-def/src/nameres/collector.rs | 16 +++--- 2 files changed, 35 insertions(+), 51 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 2a277e4c54..0836d5758b 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -63,13 +63,13 @@ use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; pub(crate) use crate::item_tree::lower::{lower_use_tree, visibility_from_ast}; #[derive(Copy, Clone, Eq, PartialEq)] -pub struct RawVisibilityId(u32); +pub(crate) struct RawVisibilityId(u32); impl RawVisibilityId { - pub const PUB: Self = RawVisibilityId(u32::MAX); - pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1); - pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2); - pub const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3); + const PUB: Self = RawVisibilityId(u32::MAX); + const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1); + const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2); + const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3); } impl fmt::Debug for RawVisibilityId { @@ -188,12 +188,12 @@ impl ItemTree { } /// Returns the inner attributes of the source file. - pub fn top_level_raw_attrs(&self) -> &RawAttrs { + pub(crate) fn top_level_raw_attrs(&self) -> &RawAttrs { &self.top_attrs } /// Returns the inner attributes of the source file. - pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { + pub(crate) fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { Attrs::expand_cfg_attr(db, krate, self.top_attrs.clone()) } @@ -278,17 +278,12 @@ pub struct ItemTreeDataStats { } /// Trait implemented by all nodes in the item tree. -pub trait ItemTreeNode: Clone { +pub(crate) trait ItemTreeNode: Clone { type Source: AstIdNode; - - fn ast_id(&self) -> FileAstId; - - /// Looks up an instance of `Self` in an item tree. - fn lookup(tree: &ItemTree, index: FileAstId) -> &Self; } #[allow(type_alias_bounds)] -pub type ItemTreeAstId = FileAstId; +pub(crate) type ItemTreeAstId = FileAstId; /// Identifies a particular [`ItemTree`]. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] @@ -298,11 +293,11 @@ pub struct TreeId { } impl TreeId { - pub fn new(file: HirFileId, block: Option) -> Self { + pub(crate) fn new(file: HirFileId, block: Option) -> Self { Self { file, block } } - pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc { + pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { match self.block { Some(block) => db.block_item_tree(block), None => db.file_item_tree(self.file), @@ -314,7 +309,7 @@ impl TreeId { self.file } - pub fn is_block(self) -> bool { + pub(crate) fn is_block(self) -> bool { self.block.is_some() } } @@ -347,17 +342,6 @@ macro_rules! mod_items { $( impl ItemTreeNode for $typ { type Source = $ast; - - fn ast_id(&self) -> FileAstId<$ast> { - self.ast_id - } - - fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self { - match &tree.data[&index.upcast()] { - ModItem::$typ(item) => item, - _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), - } - } } impl Index> for ItemTree { @@ -430,9 +414,9 @@ impl Index for ItemTree { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { - pub visibility: RawVisibilityId, - pub ast_id: FileAstId, - pub use_tree: UseTree, + pub(crate) visibility: RawVisibilityId, + pub(crate) ast_id: FileAstId, + pub(crate) use_tree: UseTree, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -494,7 +478,7 @@ pub enum UseTreeKind { pub struct ExternCrate { pub name: Name, pub alias: Option, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } @@ -507,14 +491,14 @@ pub struct ExternBlock { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Function { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Struct { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub shape: FieldsShape, pub ast_id: FileAstId, } @@ -522,14 +506,14 @@ pub struct Struct { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Union { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Enum { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } @@ -568,28 +552,28 @@ impl VisibilityExplicitness { pub struct Const { /// `None` for `const _: () = ();` pub name: Option, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Static { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct TraitAlias { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } @@ -601,14 +585,14 @@ pub struct Impl { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAlias { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Mod { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub(crate) kind: ModKind, pub ast_id: FileAstId, } @@ -641,7 +625,7 @@ pub struct MacroRules { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Macro2 { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 9801875ee4..4d19df0195 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, - MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, + self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2, MacroCall, + MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -1436,9 +1436,9 @@ impl DefCollector<'_> { let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { - ModItemId::Struct(strukt) => item_tree[strukt].ast_id().upcast(), - ModItemId::Union(union) => item_tree[union].ast_id().upcast(), - ModItemId::Enum(enum_) => item_tree[enum_].ast_id().upcast(), + ModItemId::Struct(strukt) => item_tree[strukt].ast_id.upcast(), + ModItemId::Union(union) => item_tree[union].ast_id.upcast(), + ModItemId::Enum(enum_) => item_tree[enum_].ast_id.upcast(), _ => { let diag = DefDiagnostic::invalid_derive_target( directive.module_id, @@ -1889,7 +1889,7 @@ impl ModCollector<'_, '_> { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { self.def_collector.export_proc_macro( proc_macro, - InFile::new(self.file_id(), self.item_tree[id].ast_id()), + InFile::new(self.file_id(), self.item_tree[id].ast_id), fn_id, ); } @@ -2369,7 +2369,7 @@ impl ModCollector<'_, '_> { } .intern(self.def_collector.db); self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id()).erase(), + InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), macro_id.into(), ); self.def_collector.define_macro_rules( @@ -2437,7 +2437,7 @@ impl ModCollector<'_, '_> { } .intern(self.def_collector.db); self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id()).erase(), + InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), macro_id.into(), ); self.def_collector.define_macro_def( From d8a6aaef966b3eaa1f4cc9f6f0e59f0842bf25da Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 12:50:04 +0200 Subject: [PATCH 09/14] Return item tree query results by ref --- crates/hir-def/src/attr.rs | 3 +- crates/hir-def/src/db.rs | 10 +- crates/hir-def/src/item_tree.rs | 158 +++++++++++------------- crates/hir-def/src/nameres/collector.rs | 10 +- 4 files changed, 82 insertions(+), 99 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index d63bd391fd..b509e69b0d 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -26,6 +26,7 @@ use crate::{ AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, VariantId, db::DefDatabase, + item_tree::block_item_tree_query, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, @@ -539,7 +540,7 @@ impl AttrsWithOwner { definition_tree_id.item_tree(db).raw_attrs(definition.upcast()).clone() } ModuleOrigin::BlockExpr { id, .. } => { - let tree = db.block_item_tree(id); + let tree = block_item_tree_query(db, id); tree.top_level_raw_attrs().clone() } }; diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 5f99693139..27fe62c4f0 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -24,7 +24,7 @@ use crate::{ }, hir::generics::GenericParams, import_map::ImportMap, - item_tree::ItemTree, + item_tree::{ItemTree, file_item_tree_query}, lang_item::{self, LangItem}, nameres::{ assoc::{ImplItems, TraitItems}, @@ -108,11 +108,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { fn expand_proc_attr_macros(&self) -> bool; /// Computes an [`ItemTree`] for the given file or macro expansion. - #[salsa::invoke(ItemTree::file_item_tree_query)] - fn file_item_tree(&self, file_id: HirFileId) -> Arc; - - #[salsa::invoke(ItemTree::block_item_tree_query)] - fn block_item_tree(&self, block_id: BlockId) -> Arc; + #[salsa::invoke(file_item_tree_query)] + #[salsa::transparent] + fn file_item_tree(&self, file_id: HirFileId) -> &ItemTree; /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution. #[salsa::invoke(macro_def)] diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 0836d5758b..90a5dd2dc7 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -85,6 +85,74 @@ impl fmt::Debug for RawVisibilityId { } } +#[salsa_macros::tracked(returns(ref))] +pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> ItemTree { + let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); + + let ctx = lower::Ctx::new(db, file_id); + let syntax = db.parse_or_expand(file_id); + let mut item_tree = match_ast! { + match syntax { + ast::SourceFile(file) => { + let top_attrs = RawAttrs::new(db, &file, ctx.span_map()); + let mut item_tree = ctx.lower_module_items(&file); + item_tree.top_attrs = top_attrs; + item_tree + }, + ast::MacroItems(items) => { + ctx.lower_module_items(&items) + }, + ast::MacroStmts(stmts) => { + // The produced statements can include items, which should be added as top-level + // items. + ctx.lower_macro_stmts(stmts) + }, + _ => { + if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) { + return Default::default(); + } + panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}"); + }, + } + }; + + item_tree.shrink_to_fit(); + item_tree +} + +#[salsa_macros::tracked(returns(ref))] +pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { + let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); + // Blocks have a tendency to be empty due to macro calls that do not expand to items, + // so deduplicate this case via `Arc` to reduce the size of the query storage here. + static EMPTY: OnceLock> = OnceLock::new(); + + let loc = block.lookup(db); + let block = loc.ast_id.to_node(db); + + 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() + && item_tree.top_level.is_empty() + && item_tree.attrs.is_empty() + && item_tree.top_attrs.is_empty() + { + EMPTY + .get_or_init(|| { + Arc::new(ItemTree { + top_level: Box::new([]), + attrs: FxHashMap::default(), + data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, + vis: ItemVisibilities { arena: Box::new([]) }, + }) + }) + .clone() + } else { + item_tree.shrink_to_fit(); + Arc::new(item_tree) + } +} /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { @@ -97,90 +165,6 @@ pub struct ItemTree { } impl ItemTree { - pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc { - let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); - static EMPTY: OnceLock> = OnceLock::new(); - - let ctx = lower::Ctx::new(db, file_id); - let syntax = db.parse_or_expand(file_id); - let mut item_tree = match_ast! { - match syntax { - ast::SourceFile(file) => { - let top_attrs = RawAttrs::new(db, &file, ctx.span_map()); - let mut item_tree = ctx.lower_module_items(&file); - item_tree.top_attrs = top_attrs; - item_tree - }, - ast::MacroItems(items) => { - ctx.lower_module_items(&items) - }, - ast::MacroStmts(stmts) => { - // The produced statements can include items, which should be added as top-level - // items. - ctx.lower_macro_stmts(stmts) - }, - _ => { - if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) { - return Default::default(); - } - panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}"); - }, - } - }; - - if item_tree.data.is_empty() - && item_tree.top_level.is_empty() - && item_tree.attrs.is_empty() - && item_tree.top_attrs.is_empty() - { - EMPTY - .get_or_init(|| { - Arc::new(ItemTree { - top_level: Box::new([]), - attrs: FxHashMap::default(), - data: FxHashMap::default(), - top_attrs: RawAttrs::EMPTY, - vis: ItemVisibilities { arena: Box::new([]) }, - }) - }) - .clone() - } else { - item_tree.shrink_to_fit(); - Arc::new(item_tree) - } - } - - pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { - let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); - static EMPTY: OnceLock> = OnceLock::new(); - - let loc = block.lookup(db); - let block = loc.ast_id.to_node(db); - - 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() - && item_tree.top_level.is_empty() - && item_tree.attrs.is_empty() - && item_tree.top_attrs.is_empty() - { - EMPTY - .get_or_init(|| { - Arc::new(ItemTree { - top_level: Box::new([]), - attrs: FxHashMap::default(), - data: FxHashMap::default(), - top_attrs: RawAttrs::EMPTY, - vis: ItemVisibilities { arena: Box::new([]) }, - }) - }) - .clone() - } else { - item_tree.shrink_to_fit(); - Arc::new(item_tree) - } - } - /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. pub(crate) fn top_level_items(&self) -> &[ModItemId] { @@ -297,10 +281,10 @@ impl TreeId { Self { file, block } } - pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { + pub(crate) fn item_tree<'db>(&self, db: &'db dyn DefDatabase) -> &'db ItemTree { match self.block { - Some(block) => db.block_item_tree(block), - None => db.file_item_tree(self.file), + Some(block) => block_item_tree_query(db, block), + None => file_item_tree_query(db, self.file), } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 4d19df0195..3b2488c8ea 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -357,7 +357,7 @@ impl DefCollector<'_> { macro_depth: 0, module_id: DefMap::ROOT, tree_id: TreeId::new(file_id.into(), None), - item_tree: &item_tree, + item_tree, mod_dir: ModDir::root(), } .collect_in_top_module(item_tree.top_level_items()); @@ -378,7 +378,7 @@ impl DefCollector<'_> { macro_depth: 0, module_id: DefMap::ROOT, tree_id, - item_tree: &item_tree, + item_tree, mod_dir: ModDir::root(), } .collect_in_top_module(item_tree.top_level_items()); @@ -1381,7 +1381,7 @@ impl DefCollector<'_> { macro_depth: directive.depth, module_id: directive.module_id, tree_id: *tree, - item_tree: &item_tree, + item_tree, mod_dir, } .collect(&[*mod_item], directive.container); @@ -1570,7 +1570,7 @@ impl DefCollector<'_> { macro_depth: depth, tree_id: TreeId::new(file_id, None), module_id, - item_tree: &item_tree, + item_tree, mod_dir, } .collect(item_tree.top_level_items(), container); @@ -2142,7 +2142,7 @@ impl ModCollector<'_, '_> { macro_depth: self.macro_depth, module_id, tree_id: TreeId::new(file_id.into(), None), - item_tree: &item_tree, + item_tree, mod_dir, } .collect_in_top_module(item_tree.top_level_items()); From 17d848a1bba641a3722d87e4c19e24afc4fd32ce Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 14:01:46 +0200 Subject: [PATCH 10/14] Fix tests --- crates/hir-def/src/nameres/tests/incremental.rs | 12 ++++++------ crates/hir-ty/src/tests/incremental.rs | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs index 948e8bed66..7a4ea62f12 100644 --- a/crates/hir-def/src/nameres/tests/incremental.rs +++ b/crates/hir-def/src/nameres/tests/incremental.rs @@ -348,7 +348,7 @@ m!(Z); assert_eq!(module_data.scope.resolutions().count(), 4); }); let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); + events.iter().filter(|it| it.contains("file_item_tree_query")).count(); assert_eq!(n_recalculated_item_trees, 6); let n_reparsed_macros = events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); @@ -370,7 +370,7 @@ m!(Z); assert_eq!(module_data.scope.resolutions().count(), 4); }); let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); + events.iter().filter(|it| it.contains("file_item_tree_query")).count(); assert_eq!(n_recalculated_item_trees, 1, "{events:#?}"); let n_reparsed_macros = events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); @@ -405,10 +405,10 @@ pub type Ty = (); db.file_item_tree(pos.file_id.into()); }); let n_calculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); - assert_eq!(n_calculated_item_trees, 1); + events.iter().filter(|it| it.contains("file_item_tree_query")).count(); + assert_eq!(n_calculated_item_trees, 1, "{events:#?}"); let n_parsed_files = events.iter().filter(|it| it.contains("parse")).count(); - assert_eq!(n_parsed_files, 1); + assert_eq!(n_parsed_files, 1, "{events:#?}"); } // FIXME(salsa-transition): bring this back @@ -446,6 +446,6 @@ pub type Ty = (); } }); let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count(); - assert_eq!(n_reparsed_files, 0); + assert_eq!(n_reparsed_files, 0, "{events:?}"); } } diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs index a055ef879d..74f6bbb030 100644 --- a/crates/hir-ty/src/tests/incremental.rs +++ b/crates/hir-ty/src/tests/incremental.rs @@ -156,7 +156,7 @@ pub struct NewStruct { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), @@ -216,7 +216,7 @@ pub enum SomeEnum { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), @@ -273,7 +273,7 @@ fn bar() -> f32 { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), @@ -342,7 +342,7 @@ impl SomeStruct { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), From ace69d93e07ec736569cc9e64d935780637e0767 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 08:09:44 +0200 Subject: [PATCH 11/14] Store item tree visibilities in a thin vec --- crates/hir-def/src/item_tree.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 90a5dd2dc7..85a43de6ff 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -56,6 +56,7 @@ use rustc_hash::FxHashMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; @@ -144,7 +145,7 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc attrs: FxHashMap::default(), data: FxHashMap::default(), top_attrs: RawAttrs::EMPTY, - vis: ItemVisibilities { arena: Box::new([]) }, + vis: ItemVisibilities { arena: ThinVec::new() }, }) }) .clone() @@ -229,29 +230,40 @@ impl ItemTree { #[derive(Default, Debug, Eq, PartialEq)] struct ItemVisibilities { - arena: Box<[RawVisibility]>, + arena: ThinVec, } #[derive(Debug, Clone, Eq, PartialEq)] enum ModItem { 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 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. +#[cfg(target_pointer_width = "64")] +const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 5]>()]; + #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { pub traits: usize, From 65e2e2c083486cb777e4156b33c89ee99b720c67 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 08:24:50 +0200 Subject: [PATCH 12/14] Split mod items into small and big variants --- crates/hir-def/src/item_tree.rs | 103 +++++++++++++++----------- crates/hir-def/src/item_tree/lower.rs | 43 +++++------ crates/intern/src/symbol.rs | 1 - 3 files changed, 81 insertions(+), 66 deletions(-) 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, From 048a01a05db0f359ec1f05e9d7d9c80b12432ad0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 08:43:56 +0200 Subject: [PATCH 13/14] Remove ast ids from item tree mod items --- crates/hir-def/src/item_tree.rs | 52 ++++------ crates/hir-def/src/item_tree/lower.rs | 40 ++++---- crates/hir-def/src/item_tree/pretty.rs | 68 ++++++------- crates/hir-def/src/nameres/collector.rs | 124 ++++++++++-------------- 4 files changed, 122 insertions(+), 162 deletions(-) diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 5b9da17231..bf482d33e7 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -212,13 +212,13 @@ impl ItemTree { SmallModItem::Trait(_) => traits += 1, SmallModItem::Impl(_) => impls += 1, SmallModItem::MacroRules(_) => macro_rules += 1, + SmallModItem::MacroCall(_) => macro_calls += 1, _ => {} } } for item in self.big_data.values() { match item { BigModItem::Mod(_) => mods += 1, - BigModItem::MacroCall(_) => macro_calls += 1, _ => {} } } @@ -246,11 +246,14 @@ struct ItemVisibilities { enum SmallModItem { Const(Const), Enum(Enum), + ExternBlock(ExternBlock), Function(Function), Impl(Impl), Macro2(Macro2), + MacroCall(MacroCall), MacroRules(MacroRules), Static(Static), + Struct(Struct), Trait(Trait), TraitAlias(TraitAlias), TypeAlias(TypeAlias), @@ -259,11 +262,8 @@ enum SmallModItem { #[derive(Debug, Clone, Eq, PartialEq)] enum BigModItem { - ExternBlock(ExternBlock), ExternCrate(ExternCrate), - MacroCall(MacroCall), Mod(Mod), - Struct(Struct), Use(Use), } @@ -370,23 +370,23 @@ macro_rules! mod_items { mod_items! { ModItemId -> - 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, + Enum in small_data -> ast::Enum, + ExternBlock in small_data -> ast::ExternBlock, + ExternCrate in big_data -> ast::ExternCrate, + Function in small_data -> ast::Fn, + Impl in small_data -> ast::Impl, + Macro2 in small_data -> ast::MacroDef, + MacroCall in small_data -> ast::MacroCall, + MacroRules in small_data -> ast::MacroRules, + Mod in big_data -> ast::Module, Static in small_data -> ast::Static, + Struct in small_data -> ast::Struct, 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, + Union in small_data -> ast::Union, + Use in big_data -> ast::Use, } impl Index for ItemTree { @@ -425,7 +425,6 @@ impl Index for ItemTree { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { pub(crate) visibility: RawVisibilityId, - pub(crate) ast_id: FileAstId, pub(crate) use_tree: UseTree, } @@ -490,12 +489,10 @@ pub struct ExternCrate { pub name: Name, pub alias: Option, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { - pub ast_id: FileAstId, pub(crate) children: Box<[ModItemId]>, } @@ -503,7 +500,6 @@ pub struct ExternBlock { pub struct Function { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -511,21 +507,18 @@ pub struct Struct { pub name: Name, pub(crate) visibility: RawVisibilityId, pub shape: FieldsShape, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Union { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Enum { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -564,40 +557,33 @@ pub struct Const { /// `None` for `const _: () = ();` pub name: Option, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Static { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct TraitAlias { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Impl { - pub ast_id: FileAstId, -} +pub struct Impl {} #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAlias { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -605,7 +591,6 @@ pub struct Mod { pub name: Name, pub(crate) visibility: RawVisibilityId, pub(crate) kind: ModKind, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -620,7 +605,6 @@ pub(crate) enum ModKind { pub struct MacroCall { /// Path to the called macro. pub path: Interned, - pub ast_id: FileAstId, pub expand_to: ExpandTo, pub ctxt: SyntaxContext, } @@ -629,7 +613,6 @@ pub struct MacroCall { pub struct MacroRules { /// The name of the declared macro. pub name: Name, - pub ast_id: FileAstId, } /// "Macros 2.0" macro definition. @@ -637,7 +620,6 @@ pub struct MacroRules { pub struct Macro2 { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 6ae745bb9a..fe1b8e3134 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -168,8 +168,8 @@ impl<'a> Ctx<'a> { let name = strukt.name()?.as_name(); 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.big_data.insert(ast_id.upcast(), BigModItem::Struct(res)); + let res = Struct { name, visibility, shape }; + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Struct(res)); Some(ast_id) } @@ -178,7 +178,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); - let res = Union { name, visibility, ast_id }; + let res = Union { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Union(res)); Some(ast_id) } @@ -187,7 +187,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(enum_); let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); - let res = Enum { name, visibility, ast_id }; + let res = Enum { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Enum(res)); Some(ast_id) } @@ -198,7 +198,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(func); - let res = Function { name, visibility, ast_id }; + let res = Function { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Function(res)); Some(ast_id) @@ -211,7 +211,7 @@ impl<'a> Ctx<'a> { let name = type_alias.name()?.as_name(); 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 }; + let res = TypeAlias { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TypeAlias(res)); Some(ast_id) } @@ -220,7 +220,7 @@ impl<'a> Ctx<'a> { let name = static_.name()?.as_name(); let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); - let res = Static { name, visibility, ast_id }; + let res = Static { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Static(res)); Some(ast_id) } @@ -229,7 +229,7 @@ impl<'a> Ctx<'a> { let name = konst.name().map(|it| it.as_name()); let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); - let res = Const { name, visibility, ast_id }; + let res = Const { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Const(res)); ast_id } @@ -251,7 +251,7 @@ impl<'a> Ctx<'a> { } }; let ast_id = self.source_ast_id_map.ast_id(module); - let res = Mod { name, visibility, kind, ast_id }; + let res = Mod { name, visibility, kind }; self.tree.big_data.insert(ast_id.upcast(), BigModItem::Mod(res)); Some(ast_id) } @@ -261,7 +261,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(trait_def); let ast_id = self.source_ast_id_map.ast_id(trait_def); - let def = Trait { name, visibility, ast_id }; + let def = Trait { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Trait(def)); Some(ast_id) } @@ -274,7 +274,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(trait_alias_def); let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); - let alias = TraitAlias { name, visibility, ast_id }; + let alias = TraitAlias { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TraitAlias(alias)); Some(ast_id) } @@ -283,7 +283,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(impl_def); // 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 }; + let res = Impl {}; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Impl(res)); ast_id } @@ -295,7 +295,7 @@ impl<'a> Ctx<'a> { self.span_map().span_for_range(range).ctx })?; - let res = Use { visibility, ast_id, use_tree }; + let res = Use { visibility, use_tree }; self.tree.big_data.insert(ast_id.upcast(), BigModItem::Use(res)); Some(ast_id) } @@ -311,7 +311,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(extern_crate); let ast_id = self.source_ast_id_map.ast_id(extern_crate); - let res = ExternCrate { name, alias, visibility, ast_id }; + let res = ExternCrate { name, alias, visibility }; self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternCrate(res)); Some(ast_id) } @@ -325,8 +325,8 @@ 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.big_data.insert(ast_id.upcast(), BigModItem::MacroCall(res)); + let res = MacroCall { path, expand_to, ctxt: span_map.span_for_range(range).ctx }; + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroCall(res)); Some(ast_id) } @@ -334,7 +334,7 @@ impl<'a> Ctx<'a> { let name = m.name()?; let ast_id = self.source_ast_id_map.ast_id(m); - let res = MacroRules { name: name.as_name(), ast_id }; + let res = MacroRules { name: name.as_name() }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroRules(res)); Some(ast_id) } @@ -345,7 +345,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let visibility = self.lower_visibility(m); - let res = Macro2 { name: name.as_name(), ast_id, visibility }; + let res = Macro2 { name: name.as_name(), visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Macro2(res)); Some(ast_id) } @@ -372,8 +372,8 @@ impl<'a> Ctx<'a> { .collect() }); - let res = ExternBlock { ast_id, children }; - self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternBlock(res)); + let res = ExternBlock { children }; + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::ExternBlock(res)); ast_id } diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 11b9156898..eb97081128 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -161,16 +161,16 @@ impl Printer<'_> { self.print_attrs_of(item, "\n"); match item { - ModItemId::Use(it) => { - let Use { visibility, use_tree, ast_id } = &self.tree[it]; + ModItemId::Use(ast_id) => { + let Use { visibility, use_tree } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "use "); self.print_use_tree(use_tree); wln!(self, ";"); } - ModItemId::ExternCrate(it) => { - let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it]; + ModItemId::ExternCrate(ast_id) => { + let ExternCrate { name, alias, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "extern crate {}", name.display(self.db, self.edition)); @@ -179,8 +179,8 @@ impl Printer<'_> { } wln!(self, ";"); } - ModItemId::ExternBlock(it) => { - let ExternBlock { ast_id, children } = &self.tree[it]; + ModItemId::ExternBlock(ast_id) => { + let ExternBlock { children } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); w!(self, "extern {{"); self.indented(|this| { @@ -190,14 +190,14 @@ impl Printer<'_> { }); wln!(self, "}}"); } - ModItemId::Function(it) => { - let Function { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Function(ast_id) => { + let Function { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "fn {};", name.display(self.db, self.edition)); } - ModItemId::Struct(it) => { - let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it]; + ModItemId::Struct(ast_id) => { + let Struct { visibility, name, shape: kind } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "struct {}", name.display(self.db, self.edition)); @@ -208,22 +208,22 @@ impl Printer<'_> { wln!(self, ";"); } } - ModItemId::Union(it) => { - let Union { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Union(ast_id) => { + let Union { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "union {}", name.display(self.db, self.edition)); self.print_fields(FieldsShape::Record); wln!(self); } - ModItemId::Enum(it) => { - let Enum { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Enum(ast_id) => { + let Enum { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition)); } - ModItemId::Const(it) => { - let Const { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Const(ast_id) => { + let Const { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "const "); @@ -233,8 +233,8 @@ impl Printer<'_> { } wln!(self, " = _;"); } - ModItemId::Static(it) => { - let Static { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Static(ast_id) => { + let Static { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "static "); @@ -242,33 +242,33 @@ impl Printer<'_> { w!(self, " = _;"); wln!(self); } - ModItemId::Trait(it) => { - let Trait { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Trait(ast_id) => { + let Trait { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition)); } - ModItemId::TraitAlias(it) => { - let TraitAlias { name, visibility, ast_id } = &self.tree[it]; + ModItemId::TraitAlias(ast_id) => { + let TraitAlias { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); } - ModItemId::Impl(it) => { - let Impl { ast_id } = &self.tree[it]; + ModItemId::Impl(ast_id) => { + let Impl {} = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); w!(self, "impl {{ ... }}"); } - ModItemId::TypeAlias(it) => { - let TypeAlias { name, visibility, ast_id } = &self.tree[it]; + ModItemId::TypeAlias(ast_id) => { + let TypeAlias { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "type {}", name.display(self.db, self.edition)); w!(self, ";"); wln!(self); } - ModItemId::Mod(it) => { - let Mod { name, visibility, kind, ast_id } = &self.tree[it]; + ModItemId::Mod(ast_id) => { + let Mod { name, visibility, kind } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "mod {}", name.display(self.db, self.edition)); @@ -287,8 +287,8 @@ impl Printer<'_> { } } } - ModItemId::MacroCall(it) => { - let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; + ModItemId::MacroCall(ast_id) => { + let MacroCall { path, expand_to, ctxt } = &self.tree[ast_id]; let _ = writeln!( self, "// AstId: {:#?}, SyntaxContextId: {}, ExpandTo: {:?}", @@ -298,13 +298,13 @@ impl Printer<'_> { ); wln!(self, "{}!(...);", path.display(self.db, self.edition)); } - ModItemId::MacroRules(it) => { - let MacroRules { name, ast_id } = &self.tree[it]; + ModItemId::MacroRules(ast_id) => { + let MacroRules { name } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db, self.edition)); } - ModItemId::Macro2(it) => { - let Macro2 { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Macro2(ast_id) => { + let Macro2 { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "macro {} {{ ... }}", name.display(self.db, self.edition)); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 3b2488c8ea..185cc0596b 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1434,11 +1434,10 @@ impl DefCollector<'_> { // normal (as that would just be an identity expansion with extra output) // Instead we treat derive attributes special and apply them separately. - let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { - ModItemId::Struct(strukt) => item_tree[strukt].ast_id.upcast(), - ModItemId::Union(union) => item_tree[union].ast_id.upcast(), - ModItemId::Enum(enum_) => item_tree[enum_].ast_id.upcast(), + ModItemId::Struct(ast_id) => ast_id.upcast(), + ModItemId::Union(ast_id) => ast_id.upcast(), + ModItemId::Enum(ast_id) => ast_id.upcast(), _ => { let diag = DefDiagnostic::invalid_derive_target( directive.module_id, @@ -1750,11 +1749,9 @@ impl ModCollector<'_, '_> { match item { ModItemId::Mod(m) => self.collect_module(m, &attrs), ModItemId::Use(item_tree_id) => { - let id = UseLoc { - container: module, - id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id), - } - .intern(db); + let id = + UseLoc { container: module, id: InFile::new(self.file_id(), item_tree_id) } + .intern(db); let is_prelude = attrs.by_key(sym::prelude_import).exists(); Import::from_use( self.item_tree, @@ -1772,12 +1769,12 @@ impl ModCollector<'_, '_> { ) } ModItemId::ExternCrate(item_tree_id) => { - let item_tree::ExternCrate { name, visibility, alias, ast_id } = + let item_tree::ExternCrate { name, visibility, alias } = &self.item_tree[item_tree_id]; let id = ExternCrateLoc { container: module, - id: InFile::new(self.tree_id.file_id(), *ast_id), + id: InFile::new(self.tree_id.file_id(), item_tree_id), } .intern(db); def_map.modules[self.module_id].scope.define_extern_crate_decl(id); @@ -1840,7 +1837,7 @@ impl ModCollector<'_, '_> { self.def_collector.def_map.diagnostics.push( DefDiagnostic::unresolved_extern_crate( module_id, - InFile::new(self.file_id(), *ast_id), + InFile::new(self.file_id(), item_tree_id), ), ); } @@ -1848,7 +1845,7 @@ impl ModCollector<'_, '_> { ModItemId::ExternBlock(block) => { let extern_block_id = ExternBlockLoc { container: module, - id: InFile::new(self.file_id(), self.item_tree[block].ast_id), + id: InFile::new(self.file_id(), block), } .intern(db); self.def_collector.def_map.modules[self.module_id] @@ -1859,26 +1856,20 @@ impl ModCollector<'_, '_> { ItemContainerId::ExternBlockId(extern_block_id), ) } - ModItemId::MacroCall(mac) => { - self.collect_macro_call(&self.item_tree[mac], container) - } + ModItemId::MacroCall(mac) => self.collect_macro_call(mac, container), ModItemId::MacroRules(id) => self.collect_macro_rules(id, module), ModItemId::Macro2(id) => self.collect_macro_def(id, module), ModItemId::Impl(imp) => { - let impl_id = ImplLoc { - container: module, - id: InFile::new(self.file_id(), self.item_tree[imp].ast_id), - } - .intern(db); + let impl_id = + ImplLoc { container: module, id: InFile::new(self.file_id(), imp) } + .intern(db); self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) } ModItemId::Function(id) => { let it = &self.item_tree[id]; - let fn_id = FunctionLoc { - container, - id: InFile::new(self.tree_id.file_id(), it.ast_id), - } - .intern(db); + let fn_id = + FunctionLoc { container, id: InFile::new(self.tree_id.file_id(), id) } + .intern(db); let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1889,7 +1880,7 @@ impl ModCollector<'_, '_> { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { self.def_collector.export_proc_macro( proc_macro, - InFile::new(self.file_id(), self.item_tree[id].ast_id), + InFile::new(self.file_id(), id), fn_id, ); } @@ -1903,7 +1894,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - StructLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } + StructLoc { container: module, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1917,7 +1908,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - UnionLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } + UnionLoc { container: module, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1927,11 +1918,9 @@ impl ModCollector<'_, '_> { } ModItemId::Enum(id) => { let it = &self.item_tree[id]; - let enum_ = EnumLoc { - container: module, - id: InFile::new(self.tree_id.file_id(), it.ast_id), - } - .intern(db); + let enum_ = + EnumLoc { container: module, id: InFile::new(self.tree_id.file_id(), id) } + .intern(db); let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); @@ -1939,7 +1928,7 @@ impl ModCollector<'_, '_> { ModItemId::Const(id) => { let it = &self.item_tree[id]; let const_id = - ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) } + ConstLoc { container, id: InFile::new(self.tree_id.file_id(), id) } .intern(db); match &it.name { @@ -1962,7 +1951,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - StaticLoc { container, id: InFile::new(self.file_id(), it.ast_id) } + StaticLoc { container, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1976,7 +1965,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TraitLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } + TraitLoc { container: module, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1990,12 +1979,9 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TraitAliasLoc { - container: module, - id: InFile::new(self.file_id(), it.ast_id), - } - .intern(db) - .into(), + TraitAliasLoc { container: module, id: InFile::new(self.file_id(), id) } + .intern(db) + .into(), &it.name, vis, false, @@ -2007,7 +1993,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TypeAliasLoc { container, id: InFile::new(self.file_id(), it.ast_id) } + TypeAliasLoc { container, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -2070,16 +2056,16 @@ impl ModCollector<'_, '_> { ); } - fn collect_module(&mut self, module_id: ItemTreeAstId, attrs: &Attrs) { + fn collect_module(&mut self, module_ast_id: ItemTreeAstId, attrs: &Attrs) { let path_attr = attrs.by_key(sym::path).string_value_unescape(); let is_macro_use = attrs.by_key(sym::macro_use).exists(); - let module = &self.item_tree[module_id]; + let module = &self.item_tree[module_ast_id]; match &module.kind { // inline module, just recurse ModKind::Inline { items } => { let module_id = self.push_child_module( module.name.clone(), - module.ast_id, + module_ast_id, None, &self.item_tree[module.visibility], ); @@ -2104,7 +2090,7 @@ impl ModCollector<'_, '_> { } // out of line module, resolve, parse and recurse ModKind::Outline => { - let ast_id = AstId::new(self.file_id(), module.ast_id); + let ast_id = AstId::new(self.file_id(), module_ast_id); let db = self.def_collector.db; match self.mod_dir.resolve_declaration( db, @@ -2123,10 +2109,7 @@ impl ModCollector<'_, '_> { match is_enabled { Err(cfg) => { self.emit_unconfigured_diagnostic( - InFile::new( - self.file_id(), - self.item_tree[module_id].ast_id.erase(), - ), + InFile::new(self.file_id(), module_ast_id.erase()), &cfg, ); } @@ -2295,11 +2278,11 @@ impl ModCollector<'_, '_> { Ok(()) } - fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { + fn collect_macro_rules(&mut self, ast_id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; - let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); - let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); + let mac = &self.item_tree[ast_id]; + let attrs = self.item_tree.attrs(self.def_collector.db, krate, ast_id.upcast()); + let f_ast_id = InFile::new(self.file_id(), ast_id.upcast()); let export_attr = || attrs.by_key(sym::macro_export); @@ -2346,7 +2329,7 @@ impl ModCollector<'_, '_> { self.def_collector .def_map .diagnostics - .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id)); + .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id)); return; } } @@ -2362,16 +2345,13 @@ impl ModCollector<'_, '_> { let macro_id = MacroRulesLoc { container: module, - id: InFile::new(self.file_id(), mac.ast_id), + id: InFile::new(self.file_id(), ast_id), flags, expander, edition: self.def_collector.def_map.data.edition, } .intern(self.def_collector.db); - self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), - macro_id.into(), - ); + self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into()); self.def_collector.define_macro_rules( self.module_id, mac.name.clone(), @@ -2380,14 +2360,14 @@ impl ModCollector<'_, '_> { ); } - fn collect_macro_def(&mut self, id: ItemTreeAstId, module: ModuleId) { + fn collect_macro_def(&mut self, ast_id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; - let mac = &self.item_tree[id]; - let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); + let mac = &self.item_tree[ast_id]; + let attrs = self.item_tree.attrs(self.def_collector.db, krate, ast_id.upcast()); + let f_ast_id = InFile::new(self.file_id(), ast_id.upcast()); // Case 1: builtin macros let mut helpers_opt = None; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { if let Some(expander) = find_builtin_macro(&mac.name) { match expander { @@ -2419,7 +2399,7 @@ impl ModCollector<'_, '_> { self.def_collector .def_map .diagnostics - .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id)); + .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id)); return; } } else { @@ -2430,16 +2410,13 @@ impl ModCollector<'_, '_> { let macro_id = Macro2Loc { container: module, - id: InFile::new(self.file_id(), mac.ast_id), + id: InFile::new(self.file_id(), ast_id), expander, allow_internal_unsafe, edition: self.def_collector.def_map.data.edition, } .intern(self.def_collector.db); - self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), - macro_id.into(), - ); + self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into()); self.def_collector.define_macro_def( self.module_id, mac.name.clone(), @@ -2458,9 +2435,10 @@ impl ModCollector<'_, '_> { fn collect_macro_call( &mut self, - &MacroCall { ref path, ast_id, expand_to, ctxt }: &MacroCall, + ast_id: FileAstId, container: ItemContainerId, ) { + let &MacroCall { ref path, expand_to, ctxt } = &self.item_tree[ast_id]; let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path.clone()); let db = self.def_collector.db; From 16ebd2990f64978789955613785ad2301dba7fc3 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 09:05:50 +0200 Subject: [PATCH 14/14] Remove unnecessary item tree query calls --- crates/hir-def/src/nameres/collector.rs | 96 ++++++++++++------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 185cc0596b..29f94ac2dc 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -36,7 +36,7 @@ use crate::{ item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2, MacroCall, - MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, + MacroRules, Mod, ModItemId, ModKind, TreeId, }, macro_call_as_call_id, nameres::{ @@ -140,8 +140,6 @@ struct ImportSource { id: UseId, is_prelude: bool, kind: ImportKind, - tree: TreeId, - item: FileAstId, } #[derive(Debug, Eq, PartialEq)] @@ -155,7 +153,6 @@ struct Import { impl Import { fn from_use( tree: &ItemTree, - tree_id: TreeId, item: FileAstId, id: UseId, is_prelude: bool, @@ -168,7 +165,7 @@ impl Import { path, alias, visibility: visibility.clone(), - source: ImportSource { use_tree: idx, id, is_prelude, kind, tree: tree_id, item }, + source: ImportSource { use_tree: idx, id, is_prelude, kind }, }); }); } @@ -183,15 +180,15 @@ struct ImportDirective { } #[derive(Clone, Debug, Eq, PartialEq)] -struct MacroDirective { +struct MacroDirective<'db> { module_id: LocalModuleId, depth: usize, - kind: MacroDirectiveKind, + kind: MacroDirectiveKind<'db>, container: ItemContainerId, } #[derive(Clone, Debug, Eq, PartialEq)] -enum MacroDirectiveKind { +enum MacroDirectiveKind<'db> { FnLike { ast_id: AstIdWithPath, expand_to: ExpandTo, @@ -210,28 +207,29 @@ enum MacroDirectiveKind { attr: Attr, mod_item: ModItemId, /* is this needed? */ tree: TreeId, + item_tree: &'db ItemTree, }, } /// Walks the tree of module recursively -struct DefCollector<'a> { - db: &'a dyn DefDatabase, +struct DefCollector<'db> { + db: &'db dyn DefDatabase, def_map: DefMap, local_def_map: LocalDefMap, /// Set only in case of blocks. - crate_local_def_map: Option<&'a LocalDefMap>, + crate_local_def_map: Option<&'db LocalDefMap>, // The dependencies of the current crate, including optional deps like `test`. deps: FxHashMap, glob_imports: FxHashMap>, unresolved_imports: Vec, indeterminate_imports: Vec<(ImportDirective, PerNs)>, - unresolved_macros: Vec, + unresolved_macros: Vec>, // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't // resolve. When we emit diagnostics for unresolved imports, we only do so if the import // doesn't start with an unresolved crate's name. unresolved_extern_crates: FxHashSet, mod_dirs: FxHashMap, - cfg_options: &'a CfgOptions, + cfg_options: &'db CfgOptions, /// List of procedural macros defined by this crate. This is read from the dynamic library /// built by the build system, and is the list of proc-macros we can actually expand. It is /// empty when proc-macro support is disabled (in which case we still do name resolution for @@ -249,7 +247,7 @@ struct DefCollector<'a> { skip_attrs: FxHashMap>, AttrId>, } -impl DefCollector<'_> { +impl<'db> DefCollector<'db> { fn seed_with_top_level(&mut self) { let _p = tracing::info_span!("seed_with_top_level").entered(); @@ -461,7 +459,7 @@ impl DefCollector<'_> { self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive .kind { - MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => { + MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree, item_tree } => { self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( directive.module_id, MacroCallKind::Attr { @@ -474,14 +472,20 @@ impl DefCollector<'_> { self.skip_attrs.insert(ast_id.ast_id.with_value(mod_item.ast_id()), attr.id); - Some((idx, directive, *mod_item, *tree)) + Some((idx, directive, *mod_item, *tree, *item_tree)) } _ => None, }); match unresolved_attr { - Some((pos, &MacroDirective { module_id, depth, container, .. }, mod_item, tree_id)) => { - let item_tree = &tree_id.item_tree(self.db); + Some(( + pos, + &MacroDirective { module_id, depth, container, .. }, + mod_item, + tree_id, + item_tree, + )) => { + // FIXME: Remove this clone let mod_dir = self.mod_dirs[&module_id].clone(); ModCollector { def_collector: self, @@ -862,8 +866,6 @@ impl DefCollector<'_> { kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), id, use_tree, - tree, - item, .. } => { let name = match &import.alias { @@ -896,13 +898,11 @@ impl DefCollector<'_> { let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { return false; }; - let item_tree = tree.item_tree(self.db); - let use_kind = item_tree[item].use_tree.kind(); - let UseTreeKind::Single { path, .. } = use_kind else { + if kind == ImportKind::Glob { return false; - }; - matches!(path.kind, PathKind::Plain | PathKind::SELF) - && path.segments().len() < 2 + } + matches!(import.path.kind, PathKind::Plain | PathKind::SELF) + && import.path.segments().len() < 2 }; if is_extern_crate_reimport_without_prefix() { def.vis = vis; @@ -1256,7 +1256,7 @@ impl DefCollector<'_> { fn resolve_macros(&mut self) -> ReachedFixedPoint { let mut macros = mem::take(&mut self.unresolved_macros); let mut resolved = Vec::new(); - let mut push_resolved = |directive: &MacroDirective, call_id| { + let mut push_resolved = |directive: &MacroDirective<'_>, call_id| { resolved.push((directive.module_id, directive.depth, directive.container, call_id)); }; @@ -1269,7 +1269,7 @@ impl DefCollector<'_> { let mut eager_callback_buffer = vec![]; let mut res = ReachedFixedPoint::Yes; // Retain unresolved macros after this round of resolution. - let mut retain = |directive: &MacroDirective| { + let mut retain = |directive: &MacroDirective<'db>| { let subns = match &directive.kind { MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang, MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => { @@ -1364,7 +1364,13 @@ impl DefCollector<'_> { return Resolved::Yes; } } - MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => { + MacroDirectiveKind::Attr { + ast_id: file_ast_id, + mod_item, + attr, + tree, + item_tree, + } => { let &AstIdWithPath { ast_id, ref path } = file_ast_id; let file_id = ast_id.file_id; @@ -1375,7 +1381,6 @@ impl DefCollector<'_> { .skip_attrs .insert(InFile::new(file_id, mod_item.ast_id()), attr.id); - let item_tree = tree.item_tree(self.db); ModCollector { def_collector: collector, macro_depth: directive.depth, @@ -1646,8 +1651,7 @@ impl DefCollector<'_> { import: Import { ref path, - source: - ImportSource { use_tree, id, is_prelude: _, kind: _, tree: _, item: _ }, + source: ImportSource { use_tree, id, is_prelude: _, kind: _ }, .. }, .. @@ -1671,12 +1675,12 @@ impl DefCollector<'_> { } /// Walks a single module, populating defs, imports and macros -struct ModCollector<'a, 'b> { - def_collector: &'a mut DefCollector<'b>, +struct ModCollector<'a, 'db> { + def_collector: &'a mut DefCollector<'db>, macro_depth: usize, module_id: LocalModuleId, tree_id: TreeId, - item_tree: &'a ItemTree, + item_tree: &'db ItemTree, mod_dir: ModDir, } @@ -1753,20 +1757,13 @@ impl ModCollector<'_, '_> { UseLoc { container: module, id: InFile::new(self.file_id(), item_tree_id) } .intern(db); let is_prelude = attrs.by_key(sym::prelude_import).exists(); - Import::from_use( - self.item_tree, - self.tree_id, - item_tree_id, - id, - is_prelude, - |import| { - self.def_collector.unresolved_imports.push(ImportDirective { - module_id: self.module_id, - import, - status: PartialResolvedImport::Unresolved, - }); - }, - ) + Import::from_use(self.item_tree, item_tree_id, id, is_prelude, |import| { + self.def_collector.unresolved_imports.push(ImportDirective { + module_id: self.module_id, + import, + status: PartialResolvedImport::Unresolved, + }); + }) } ModItemId::ExternCrate(item_tree_id) => { let item_tree::ExternCrate { name, visibility, alias } = @@ -2268,6 +2265,7 @@ impl ModCollector<'_, '_> { attr: attr.clone(), mod_item, tree: self.tree_id, + item_tree: self.item_tree, }, container, });