@@ -86,9 +86,10 @@ impl fmt::Debug for RawVisibilityId {
8686 }
8787}
8888
89- #[ salsa_macros:: tracked( returns( ref ) ) ]
90- pub ( crate ) fn file_item_tree_query ( db : & dyn DefDatabase , file_id : HirFileId ) -> ItemTree {
89+ #[ salsa_macros:: tracked( returns( deref ) ) ]
90+ pub ( crate ) fn file_item_tree_query ( db : & dyn DefDatabase , file_id : HirFileId ) -> Arc < ItemTree > {
9191 let _p = tracing:: info_span!( "file_item_tree_query" , ?file_id) . entered ( ) ;
92+ static EMPTY : OnceLock < Arc < ItemTree > > = OnceLock :: new ( ) ;
9293
9394 let ctx = lower:: Ctx :: new ( db, file_id) ;
9495 let syntax = db. parse_or_expand ( file_id) ;
@@ -116,28 +117,49 @@ pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) ->
116117 } ,
117118 }
118119 } ;
119-
120- item_tree. shrink_to_fit ( ) ;
121- item_tree
120+ let ItemTree { top_level, top_attrs, attrs, vis, big_data, small_data } = & item_tree;
121+ if small_data. is_empty ( )
122+ && big_data. is_empty ( )
123+ && top_level. is_empty ( )
124+ && attrs. is_empty ( )
125+ && top_attrs. is_empty ( )
126+ && vis. arena . is_empty ( )
127+ {
128+ EMPTY
129+ . get_or_init ( || {
130+ Arc :: new ( ItemTree {
131+ top_level : Box :: new ( [ ] ) ,
132+ attrs : FxHashMap :: default ( ) ,
133+ small_data : FxHashMap :: default ( ) ,
134+ big_data : FxHashMap :: default ( ) ,
135+ top_attrs : RawAttrs :: EMPTY ,
136+ vis : ItemVisibilities { arena : ThinVec :: new ( ) } ,
137+ } )
138+ } )
139+ . clone ( )
140+ } else {
141+ item_tree. shrink_to_fit ( ) ;
142+ Arc :: new ( item_tree)
143+ }
122144}
123145
124- #[ salsa_macros:: tracked( returns( ref ) ) ]
146+ #[ salsa_macros:: tracked( returns( deref ) ) ]
125147pub ( crate ) fn block_item_tree_query ( db : & dyn DefDatabase , block : BlockId ) -> Arc < ItemTree > {
126148 let _p = tracing:: info_span!( "block_item_tree_query" , ?block) . entered ( ) ;
127- // Blocks have a tendency to be empty due to macro calls that do not expand to items,
128- // so deduplicate this case via `Arc` to reduce the size of the query storage here.
129149 static EMPTY : OnceLock < Arc < ItemTree > > = OnceLock :: new ( ) ;
130150
131151 let loc = block. lookup ( db) ;
132152 let block = loc. ast_id . to_node ( db) ;
133153
134154 let ctx = lower:: Ctx :: new ( db, loc. ast_id . file_id ) ;
135155 let mut item_tree = ctx. lower_block ( & block) ;
136- if item_tree. small_data . is_empty ( )
137- && item_tree. big_data . is_empty ( )
138- && item_tree. top_level . is_empty ( )
139- && item_tree. attrs . is_empty ( )
140- && item_tree. top_attrs . is_empty ( )
156+ let ItemTree { top_level, top_attrs, attrs, vis, big_data, small_data } = & item_tree;
157+ if small_data. is_empty ( )
158+ && big_data. is_empty ( )
159+ && top_level. is_empty ( )
160+ && attrs. is_empty ( )
161+ && top_attrs. is_empty ( )
162+ && vis. arena . is_empty ( )
141163 {
142164 EMPTY
143165 . get_or_init ( || {
@@ -163,7 +185,6 @@ pub struct ItemTree {
163185 top_attrs : RawAttrs ,
164186 attrs : FxHashMap < FileAstId < ast:: Item > , RawAttrs > ,
165187 vis : ItemVisibilities ,
166- // FIXME: They values store the key, turn this into a FxHashSet<ModItem> instead?
167188 big_data : FxHashMap < FileAstId < ast:: Item > , BigModItem > ,
168189 small_data : FxHashMap < FileAstId < ast:: Item > , SmallModItem > ,
169190}
0 commit comments