Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_tree.rs')
| -rw-r--r-- | crates/hir-def/src/item_tree.rs | 625 |
1 files changed, 239 insertions, 386 deletions
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 81c8f56456..bf482d33e7 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,12 +51,12 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::{Arena, Idx, RawIdx}; +use la_arena::{Idx, RawIdx}; use rustc_hash::FxHashMap; -use smallvec::SmallVec; 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}; @@ -64,13 +64,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 { @@ -86,112 +86,115 @@ 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]>, - attrs: FxHashMap<AttrOwner, RawAttrs>, +#[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}"); + }, + } + }; - data: Option<Box<ItemTreeData>>, + item_tree.shrink_to_fit(); + item_tree } -impl ItemTree { - pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { - let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); - static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new(); - - 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) - }, - 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}"); - }, - } - }; +#[salsa_macros::tracked(returns(ref))] +pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> { + 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<Arc<ItemTree>> = OnceLock::new(); - 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() - { - EMPTY - .get_or_init(|| { - Arc::new(ItemTree { - top_level: SmallVec::new_const(), - attrs: FxHashMap::default(), - data: None, - }) - }) - .clone() - } else { - item_tree.shrink_to_fit(); - Arc::new(item_tree) - } - } + let loc = block.lookup(db); + let block = loc.ast_id.to_node(db); - pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> { - let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); - static EMPTY: OnceLock<Arc<ItemTree>> = 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_none() && 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, - }) + let ctx = lower::Ctx::new(db, loc.ast_id.file_id); + let mut item_tree = ctx.lower_block(&block); + 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() + { + EMPTY + .get_or_init(|| { + Arc::new(ItemTree { + top_level: Box::new([]), + attrs: FxHashMap::default(), + small_data: FxHashMap::default(), + big_data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, + vis: ItemVisibilities { arena: ThinVec::new() }, }) - .clone() - } else { - item_tree.shrink_to_fit(); - Arc::new(item_tree) - } + }) + .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 { + top_level: Box<[ModItemId]>, + top_attrs: RawAttrs, + attrs: FxHashMap<FileAstId<ast::Item>, RawAttrs>, + vis: ItemVisibilities, + // FIXME: They values store the key, turn this into a FxHashSet<ModItem> instead? + big_data: FxHashMap<FileAstId<ast::Item>, BigModItem>, + small_data: FxHashMap<FileAstId<ast::Item>, SmallModItem>, +} +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) -> &[ModItemId] { &self.top_level } /// 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(crate) 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(crate) 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<ast::Item>) -> &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<ast::Item>, + ) -> Attrs { Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone()) } @@ -199,105 +202,79 @@ 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.small_data.values() { + match item { + 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, + _ => {} + } } + 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; - top_level.shrink_to_fit(); + let ItemTree { top_level: _, attrs, big_data, small_data, vis: _, top_attrs: _ } = self; 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(); - } + big_data.shrink_to_fit(); + small_data.shrink_to_fit(); } } #[derive(Default, Debug, Eq, PartialEq)] struct ItemVisibilities { - arena: Box<[RawVisibility]>, + arena: ThinVec<RawVisibility>, } -#[derive(Default, Debug, Eq, PartialEq)] -struct ItemTreeData { - uses: Arena<Use>, - extern_crates: Arena<ExternCrate>, - extern_blocks: Arena<ExternBlock>, - functions: Arena<Function>, - structs: Arena<Struct>, - unions: Arena<Union>, - enums: Arena<Enum>, - consts: Arena<Const>, - statics: Arena<Static>, - traits: Arena<Trait>, - trait_aliases: Arena<TraitAlias>, - impls: Arena<Impl>, - type_aliases: Arena<TypeAlias>, - mods: Arena<Mod>, - macro_calls: Arena<MacroCall>, - macro_rules: Arena<MacroRules>, - macro_defs: Arena<Macro2>, +#[derive(Debug, Clone, Eq, PartialEq)] +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), + Union(Union), +} - vis: ItemVisibilities, +#[derive(Debug, Clone, Eq, PartialEq)] +enum BigModItem { + ExternCrate(ExternCrate), + Mod(Mod), + 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 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::<BigModItem>()] = [(); std::mem::size_of::<[usize; 5]>()]; +#[cfg(target_pointer_width = "64")] +const _: [(); std::mem::size_of::<SmallModItem>()] = [(); std::mem::size_of::<[usize; 3]>()]; + #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { pub traits: usize, @@ -307,73 +284,13 @@ pub struct ItemTreeDataStats { pub macro_rules: usize, } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum AttrOwner { - /// Attributes on an item. - ModItem(ModItem), - /// Inner attributes of the source file. - TopLevel, -} - -impl From<ModItem> for AttrOwner { - #[inline] - fn from(value: ModItem) -> Self { - AttrOwner::ModItem(value) - } -} - /// 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<Self::Source>; - - /// Looks up an instance of `Self` in an item tree. - fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self; } -pub struct FileItemTreeId<N>(Idx<N>); - -impl<N> FileItemTreeId<N> { - pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> + 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<N> FileItemTreeId<N> { - pub fn index(&self) -> Idx<N> { - self.0 - } -} - -impl<N> Clone for FileItemTreeId<N> { - fn clone(&self) -> Self { - *self - } -} -impl<N> Copy for FileItemTreeId<N> {} - -impl<N> PartialEq for FileItemTreeId<N> { - fn eq(&self, other: &FileItemTreeId<N>) -> bool { - self.0 == other.0 - } -} -impl<N> Eq for FileItemTreeId<N> {} - -impl<N> Hash for FileItemTreeId<N> { - fn hash<H: Hasher>(&self, state: &mut H) { - self.0.hash(state) - } -} - -impl<N> fmt::Debug for FileItemTreeId<N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} +#[allow(type_alias_bounds)] +pub(crate) type ItemTreeAstId<T: ItemTreeNode> = FileAstId<T::Source>; /// Identifies a particular [`ItemTree`]. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] @@ -383,14 +300,14 @@ pub struct TreeId { } impl TreeId { - pub fn new(file: HirFileId, block: Option<BlockId>) -> Self { + pub(crate) fn new(file: HirFileId, block: Option<BlockId>) -> Self { Self { file, block } } - pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> { + 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), } } @@ -399,85 +316,32 @@ impl TreeId { self.file } - pub fn is_block(self) -> bool { + pub(crate) fn is_block(self) -> bool { self.block.is_some() } } -#[derive(Debug)] -pub struct ItemTreeId<N> { - tree: TreeId, - pub value: FileItemTreeId<N>, -} - -impl<N> ItemTreeId<N> { - pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> 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<ItemTree> { - self.tree.item_tree(db) - } - - pub fn resolved<R>(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R - where - ItemTree: Index<FileItemTreeId<N>, Output = N>, - { - cb(&self.tree.item_tree(db)[self.value]) - } -} - -impl<N> Copy for ItemTreeId<N> {} -impl<N> Clone for ItemTreeId<N> { - fn clone(&self) -> Self { - *self - } -} - -impl<N> PartialEq for ItemTreeId<N> { - fn eq(&self, other: &Self) -> bool { - self.tree == other.tree && self.value == other.value - } -} - -impl<N> Eq for ItemTreeId<N> {} - -impl<N> Hash for ItemTreeId<N> { - fn hash<H: Hasher>(&self, state: &mut H) { - self.tree.hash(state); - self.value.hash(state); - } -} - 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(FileItemTreeId<$typ>), + $typ(FileAstId<$ast>), )+ } - impl ModItem { - pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> { + impl $mod_item { + pub(crate) fn ast_id(self) -> FileAstId<ast::Item> { match self { - $(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+ + $($mod_item::$typ(it) => it.upcast()),+ } } } $( - impl From<FileItemTreeId<$typ>> for ModItem { - fn from(id: FileItemTreeId<$typ>) -> ModItem { - ModItem::$typ(id) + impl From<FileAstId<$ast>> for $mod_item { + fn from(id: FileAstId<$ast>) -> $mod_item { + ModItemId::$typ(id) } } )+ @@ -485,21 +349,19 @@ macro_rules! mod_items { $( impl ItemTreeNode for $typ { type Source = $ast; - - fn ast_id(&self) -> FileAstId<Self::Source> { - self.ast_id - } - - fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self { - &tree.data().$fld[index] - } } - impl Index<Idx<$typ>> for ItemTree { + impl Index<FileAstId<$ast>> for ItemTree { type Output = $typ; - fn index(&self, index: Idx<$typ>) -> &Self::Output { - &self.data().$fld[index] + #[allow(unused_imports)] + fn index(&self, index: FileAstId<$ast>) -> &Self::Output { + use BigModItem::*; + use SmallModItem::*; + match &self.$fld[&index.upcast()] { + $typ(item) => item, + _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), + } } } )+ @@ -507,23 +369,24 @@ macro_rules! mod_items { } mod_items! { - 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, +ModItemId -> + 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, + TypeAlias in small_data -> ast::TypeAlias, + Union in small_data -> ast::Union, + Use in big_data -> ast::Use, } impl Index<RawVisibilityId> for ItemTree { @@ -554,31 +417,24 @@ impl Index<RawVisibilityId> for ItemTree { VisibilityExplicitness::Explicit, ) }), - _ => &self.data().vis.arena[index.0 as usize], + _ => &self.vis.arena[index.0 as usize], } } } -impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { - type Output = N; - fn index(&self, id: FileItemTreeId<N>) -> &N { - N::lookup(self, id.index()) - } -} - #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Use>, - pub use_tree: UseTree, + pub(crate) visibility: RawVisibilityId, + pub(crate) use_tree: UseTree, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct UseTree { - pub index: Idx<ast::UseTree>, kind: UseTreeKind, } +// 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 _;` @@ -632,43 +488,37 @@ pub enum UseTreeKind { pub struct ExternCrate { pub name: Name, pub alias: Option<ImportAlias>, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::ExternCrate>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { - pub ast_id: FileAstId<ast::ExternBlock>, - pub children: Box<[ModItem]>, + pub(crate) children: Box<[ModItemId]>, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Function { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Fn>, + pub(crate) visibility: RawVisibilityId, } #[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<ast::Struct>, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Union { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Union>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Enum { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Enum>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -706,55 +556,47 @@ impl VisibilityExplicitness { pub struct Const { /// `None` for `const _: () = ();` pub name: Option<Name>, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Const>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Static { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Static>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::Trait>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct TraitAlias { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::TraitAlias>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Impl { - pub ast_id: FileAstId<ast::Impl>, -} +pub struct Impl {} #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAlias { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::TypeAlias>, + pub(crate) visibility: RawVisibilityId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Mod { pub name: Name, - pub visibility: RawVisibilityId, - pub kind: ModKind, - pub ast_id: FileAstId<ast::Module>, + pub(crate) visibility: RawVisibilityId, + pub(crate) kind: ModKind, } #[derive(Debug, Clone, Eq, PartialEq)] -pub enum ModKind { +pub(crate) enum ModKind { /// `mod m { ... }` - Inline { items: Box<[ModItem]> }, + Inline { items: Box<[ModItemId]> }, /// `mod m;` Outline, } @@ -763,7 +605,6 @@ pub enum ModKind { pub struct MacroCall { /// Path to the called macro. pub path: Interned<ModPath>, - pub ast_id: FileAstId<ast::MacroCall>, pub expand_to: ExpandTo, pub ctxt: SyntaxContext, } @@ -772,15 +613,13 @@ pub struct MacroCall { pub struct MacroRules { /// The name of the declared macro. pub name: Name, - pub ast_id: FileAstId<ast::MacroRules>, } /// "Macros 2.0" macro definition. #[derive(Debug, Clone, Eq, PartialEq)] pub struct Macro2 { pub name: Name, - pub visibility: RawVisibilityId, - pub ast_id: FileAstId<ast::MacroDef>, + pub(crate) visibility: RawVisibilityId, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -793,15 +632,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<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>), ) { - 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 @@ -810,6 +651,7 @@ impl UseTree { fn expand_impl( &self, prefix: Option<ModPath>, + counting_index: &mut u32, cb: &mut impl FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>), ) { fn concat_mod_paths( @@ -845,17 +687,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 } => { @@ -867,7 +719,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); } } } |