Skip to content

Commit e51cad9

Browse files
committed
Coalesce item tree data maps
1 parent 834579f commit e51cad9

File tree

4 files changed

+138
-181
lines changed

4 files changed

+138
-181
lines changed

src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs

Lines changed: 61 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ impl fmt::Debug for RawVisibilityId {
8989
/// The item tree of a source file.
9090
#[derive(Debug, Default, Eq, PartialEq)]
9191
pub struct ItemTree {
92-
top_level: SmallVec<[ModItem; 1]>,
92+
top_level: SmallVec<[ModItemId; 1]>,
9393
// Consider splitting this into top level RawAttrs and the map?
9494
attrs: FxHashMap<AttrOwner, RawAttrs>,
9595

96-
data: Option<Box<ItemTreeData>>,
96+
vis: ItemVisibilities,
97+
data: FxHashMap<FileAstId<ast::Item>, ModItem>,
9798
}
9899

99100
impl ItemTree {
@@ -130,14 +131,15 @@ impl ItemTree {
130131
if let Some(attrs) = top_attrs {
131132
item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
132133
}
133-
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
134+
if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
134135
{
135136
EMPTY
136137
.get_or_init(|| {
137138
Arc::new(ItemTree {
138139
top_level: SmallVec::new_const(),
139140
attrs: FxHashMap::default(),
140-
data: None,
141+
data: FxHashMap::default(),
142+
vis: ItemVisibilities { arena: Box::new([]) },
141143
})
142144
})
143145
.clone()
@@ -156,14 +158,15 @@ impl ItemTree {
156158

157159
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
158160
let mut item_tree = ctx.lower_block(&block);
159-
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
161+
if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
160162
{
161163
EMPTY
162164
.get_or_init(|| {
163165
Arc::new(ItemTree {
164166
top_level: SmallVec::new_const(),
165167
attrs: FxHashMap::default(),
166-
data: None,
168+
data: FxHashMap::default(),
169+
vis: ItemVisibilities { arena: Box::new([]) },
167170
})
168171
})
169172
.clone()
@@ -175,7 +178,7 @@ impl ItemTree {
175178

176179
/// Returns an iterator over all items located at the top level of the `HirFileId` this
177180
/// `ItemTree` was created from.
178-
pub(crate) fn top_level_items(&self) -> &[ModItem] {
181+
pub(crate) fn top_level_items(&self) -> &[ModItemId] {
179182
&self.top_level
180183
}
181184

@@ -200,74 +203,33 @@ impl ItemTree {
200203
///
201204
/// For more detail, see [`ItemTreeDataStats`].
202205
pub fn item_tree_stats(&self) -> ItemTreeDataStats {
203-
match self.data {
204-
Some(ref data) => ItemTreeDataStats {
205-
traits: data.traits.len(),
206-
impls: data.impls.len(),
207-
mods: data.mods.len(),
208-
macro_calls: data.macro_calls.len(),
209-
macro_rules: data.macro_rules.len(),
210-
},
211-
None => ItemTreeDataStats::default(),
206+
let mut traits = 0;
207+
let mut impls = 0;
208+
let mut mods = 0;
209+
let mut macro_calls = 0;
210+
let mut macro_rules = 0;
211+
for item in self.data.values() {
212+
match item {
213+
ModItem::Trait(_) => traits += 1,
214+
ModItem::Impl(_) => impls += 1,
215+
ModItem::Mod(_) => mods += 1,
216+
ModItem::MacroCall(_) => macro_calls += 1,
217+
ModItem::MacroRules(_) => macro_rules += 1,
218+
_ => {}
219+
}
212220
}
221+
ItemTreeDataStats { traits, impls, mods, macro_calls, macro_rules }
213222
}
214223

215224
pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String {
216225
pretty::print_item_tree(db, self, edition)
217226
}
218227

219-
fn data(&self) -> &ItemTreeData {
220-
self.data.as_ref().expect("attempted to access data of empty ItemTree")
221-
}
222-
223-
fn data_mut(&mut self) -> &mut ItemTreeData {
224-
self.data.get_or_insert_with(Box::default)
225-
}
226-
227228
fn shrink_to_fit(&mut self) {
228-
let ItemTree { top_level, attrs, data } = self;
229+
let ItemTree { top_level, attrs, data, vis: _ } = self;
229230
top_level.shrink_to_fit();
230231
attrs.shrink_to_fit();
231-
if let Some(data) = data {
232-
let ItemTreeData {
233-
uses,
234-
extern_crates,
235-
extern_blocks,
236-
functions,
237-
structs,
238-
unions,
239-
enums,
240-
consts,
241-
statics,
242-
traits,
243-
trait_aliases,
244-
impls,
245-
type_aliases,
246-
mods,
247-
macro_calls,
248-
macro_rules,
249-
macro_defs,
250-
vis: _,
251-
} = &mut **data;
252-
253-
uses.shrink_to_fit();
254-
extern_crates.shrink_to_fit();
255-
extern_blocks.shrink_to_fit();
256-
functions.shrink_to_fit();
257-
structs.shrink_to_fit();
258-
unions.shrink_to_fit();
259-
enums.shrink_to_fit();
260-
consts.shrink_to_fit();
261-
statics.shrink_to_fit();
262-
traits.shrink_to_fit();
263-
trait_aliases.shrink_to_fit();
264-
impls.shrink_to_fit();
265-
type_aliases.shrink_to_fit();
266-
mods.shrink_to_fit();
267-
macro_calls.shrink_to_fit();
268-
macro_rules.shrink_to_fit();
269-
macro_defs.shrink_to_fit();
270-
}
232+
data.shrink_to_fit();
271233
}
272234
}
273235

@@ -276,29 +238,26 @@ struct ItemVisibilities {
276238
arena: Box<[RawVisibility]>,
277239
}
278240

279-
#[derive(Default, Debug, Eq, PartialEq)]
280-
struct ItemTreeData {
281-
uses: FxHashMap<ItemTreeAstId<Use>, Use>,
282-
extern_crates: FxHashMap<ItemTreeAstId<ExternCrate>, ExternCrate>,
283-
extern_blocks: FxHashMap<ItemTreeAstId<ExternBlock>, ExternBlock>,
284-
functions: FxHashMap<ItemTreeAstId<Function>, Function>,
285-
structs: FxHashMap<ItemTreeAstId<Struct>, Struct>,
286-
unions: FxHashMap<ItemTreeAstId<Union>, Union>,
287-
enums: FxHashMap<ItemTreeAstId<Enum>, Enum>,
288-
consts: FxHashMap<ItemTreeAstId<Const>, Const>,
289-
statics: FxHashMap<ItemTreeAstId<Static>, Static>,
290-
traits: FxHashMap<ItemTreeAstId<Trait>, Trait>,
291-
trait_aliases: FxHashMap<ItemTreeAstId<TraitAlias>, TraitAlias>,
292-
impls: FxHashMap<ItemTreeAstId<Impl>, Impl>,
293-
type_aliases: FxHashMap<ItemTreeAstId<TypeAlias>, TypeAlias>,
294-
mods: FxHashMap<ItemTreeAstId<Mod>, Mod>,
295-
macro_calls: FxHashMap<ItemTreeAstId<MacroCall>, MacroCall>,
296-
macro_rules: FxHashMap<ItemTreeAstId<MacroRules>, MacroRules>,
297-
macro_defs: FxHashMap<ItemTreeAstId<Macro2>, Macro2>,
298-
299-
vis: ItemVisibilities,
241+
#[derive(Debug, Clone, Eq, PartialEq)]
242+
enum ModItem {
243+
Const(Const),
244+
Enum(Enum),
245+
ExternBlock(ExternBlock),
246+
ExternCrate(ExternCrate),
247+
Function(Function),
248+
Impl(Impl),
249+
Macro2(Macro2),
250+
MacroCall(MacroCall),
251+
MacroRules(MacroRules),
252+
Mod(Mod),
253+
Static(Static),
254+
Struct(Struct),
255+
Trait(Trait),
256+
TraitAlias(TraitAlias),
257+
TypeAlias(TypeAlias),
258+
Union(Union),
259+
Use(Use),
300260
}
301-
302261
#[derive(Default, Debug, Eq, PartialEq)]
303262
pub struct ItemTreeDataStats {
304263
pub traits: usize,
@@ -316,9 +275,9 @@ pub enum AttrOwner {
316275
TopLevel,
317276
}
318277

319-
impl From<ModItem> for AttrOwner {
278+
impl From<ModItemId> for AttrOwner {
320279
#[inline]
321-
fn from(value: ModItem) -> Self {
280+
fn from(value: ModItemId) -> Self {
322281
AttrOwner::Item(value.ast_id().erase())
323282
}
324283
}
@@ -385,7 +344,7 @@ macro_rules! mod_items {
385344
$(
386345
impl From<FileAstId<$ast>> for $mod_item {
387346
fn from(id: FileAstId<$ast>) -> $mod_item {
388-
ModItem::$typ(id)
347+
ModItemId::$typ(id)
389348
}
390349
}
391350
)+
@@ -399,23 +358,29 @@ macro_rules! mod_items {
399358
}
400359

401360
fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self {
402-
&tree.data().$fld[&index]
361+
match &tree.data[&index.upcast()] {
362+
ModItem::$typ(item) => item,
363+
_ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index),
364+
}
403365
}
404366
}
405367

406368
impl Index<FileAstId<$ast>> for ItemTree {
407369
type Output = $typ;
408370

409371
fn index(&self, index: FileAstId<$ast>) -> &Self::Output {
410-
&self.data().$fld[&index]
372+
match &self.data[&index.upcast()] {
373+
ModItem::$typ(item) => item,
374+
_ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index),
375+
}
411376
}
412377
}
413378
)+
414379
};
415380
}
416381

417382
mod_items! {
418-
ModItem ->
383+
ModItemId ->
419384
Use in uses -> ast::Use,
420385
ExternCrate in extern_crates -> ast::ExternCrate,
421386
ExternBlock in extern_blocks -> ast::ExternBlock,
@@ -463,7 +428,7 @@ impl Index<RawVisibilityId> for ItemTree {
463428
VisibilityExplicitness::Explicit,
464429
)
465430
}),
466-
_ => &self.data().vis.arena[index.0 as usize],
431+
_ => &self.vis.arena[index.0 as usize],
467432
}
468433
}
469434
}
@@ -541,7 +506,7 @@ pub struct ExternCrate {
541506
#[derive(Debug, Clone, Eq, PartialEq)]
542507
pub struct ExternBlock {
543508
pub ast_id: FileAstId<ast::ExternBlock>,
544-
pub(crate) children: Box<[ModItem]>,
509+
pub(crate) children: Box<[ModItemId]>,
545510
}
546511

547512
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -656,7 +621,7 @@ pub struct Mod {
656621
#[derive(Debug, Clone, Eq, PartialEq)]
657622
pub(crate) enum ModKind {
658623
/// `mod m { ... }`
659-
Inline { items: Box<[ModItem]> },
624+
Inline { items: Box<[ModItemId]> },
660625
/// `mod m;`
661626
Outline,
662627
}

0 commit comments

Comments
 (0)