Skip to content

Commit 4d811e3

Browse files
committed
Return item tree query results by ref
1 parent b1c8633 commit 4d811e3

File tree

4 files changed

+82
-99
lines changed

4 files changed

+82
-99
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{
2626
AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId,
2727
VariantId,
2828
db::DefDatabase,
29+
item_tree::block_item_tree_query,
2930
lang_item::LangItem,
3031
nameres::{ModuleOrigin, ModuleSource},
3132
src::{HasChildSource, HasSource},
@@ -539,7 +540,7 @@ impl AttrsWithOwner {
539540
definition_tree_id.item_tree(db).raw_attrs(definition.upcast()).clone()
540541
}
541542
ModuleOrigin::BlockExpr { id, .. } => {
542-
let tree = db.block_item_tree(id);
543+
let tree = block_item_tree_query(db, id);
543544
tree.top_level_raw_attrs().clone()
544545
}
545546
};

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
},
2525
hir::generics::GenericParams,
2626
import_map::ImportMap,
27-
item_tree::ItemTree,
27+
item_tree::{ItemTree, file_item_tree_query},
2828
lang_item::{self, LangItem},
2929
nameres::{
3030
assoc::{ImplItems, TraitItems},
@@ -108,11 +108,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
108108
fn expand_proc_attr_macros(&self) -> bool;
109109

110110
/// Computes an [`ItemTree`] for the given file or macro expansion.
111-
#[salsa::invoke(ItemTree::file_item_tree_query)]
112-
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
113-
114-
#[salsa::invoke(ItemTree::block_item_tree_query)]
115-
fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
111+
#[salsa::invoke(file_item_tree_query)]
112+
#[salsa::transparent]
113+
fn file_item_tree(&self, file_id: HirFileId) -> &ItemTree;
116114

117115
/// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
118116
#[salsa::invoke(macro_def)]

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

Lines changed: 71 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,74 @@ impl fmt::Debug for RawVisibilityId {
8585
}
8686
}
8787

88+
#[salsa_macros::tracked(returns(ref))]
89+
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> ItemTree {
90+
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
91+
92+
let ctx = lower::Ctx::new(db, file_id);
93+
let syntax = db.parse_or_expand(file_id);
94+
let mut item_tree = match_ast! {
95+
match syntax {
96+
ast::SourceFile(file) => {
97+
let top_attrs = RawAttrs::new(db, &file, ctx.span_map());
98+
let mut item_tree = ctx.lower_module_items(&file);
99+
item_tree.top_attrs = top_attrs;
100+
item_tree
101+
},
102+
ast::MacroItems(items) => {
103+
ctx.lower_module_items(&items)
104+
},
105+
ast::MacroStmts(stmts) => {
106+
// The produced statements can include items, which should be added as top-level
107+
// items.
108+
ctx.lower_macro_stmts(stmts)
109+
},
110+
_ => {
111+
if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) {
112+
return Default::default();
113+
}
114+
panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}");
115+
},
116+
}
117+
};
118+
119+
item_tree.shrink_to_fit();
120+
item_tree
121+
}
122+
123+
#[salsa_macros::tracked(returns(ref))]
124+
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
125+
let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
126+
// Blocks have a tendency to be empty due to macro calls that do not expand to items,
127+
// so deduplicate this case via `Arc` to reduce the size of the query storage here.
128+
static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
129+
130+
let loc = block.lookup(db);
131+
let block = loc.ast_id.to_node(db);
132+
133+
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
134+
let mut item_tree = ctx.lower_block(&block);
135+
if item_tree.data.is_empty()
136+
&& item_tree.top_level.is_empty()
137+
&& item_tree.attrs.is_empty()
138+
&& item_tree.top_attrs.is_empty()
139+
{
140+
EMPTY
141+
.get_or_init(|| {
142+
Arc::new(ItemTree {
143+
top_level: Box::new([]),
144+
attrs: FxHashMap::default(),
145+
data: FxHashMap::default(),
146+
top_attrs: RawAttrs::EMPTY,
147+
vis: ItemVisibilities { arena: Box::new([]) },
148+
})
149+
})
150+
.clone()
151+
} else {
152+
item_tree.shrink_to_fit();
153+
Arc::new(item_tree)
154+
}
155+
}
88156
/// The item tree of a source file.
89157
#[derive(Debug, Default, Eq, PartialEq)]
90158
pub struct ItemTree {
@@ -97,90 +165,6 @@ pub struct ItemTree {
97165
}
98166

99167
impl ItemTree {
100-
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
101-
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
102-
static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
103-
104-
let ctx = lower::Ctx::new(db, file_id);
105-
let syntax = db.parse_or_expand(file_id);
106-
let mut item_tree = match_ast! {
107-
match syntax {
108-
ast::SourceFile(file) => {
109-
let top_attrs = RawAttrs::new(db, &file, ctx.span_map());
110-
let mut item_tree = ctx.lower_module_items(&file);
111-
item_tree.top_attrs = top_attrs;
112-
item_tree
113-
},
114-
ast::MacroItems(items) => {
115-
ctx.lower_module_items(&items)
116-
},
117-
ast::MacroStmts(stmts) => {
118-
// The produced statements can include items, which should be added as top-level
119-
// items.
120-
ctx.lower_macro_stmts(stmts)
121-
},
122-
_ => {
123-
if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) {
124-
return Default::default();
125-
}
126-
panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}");
127-
},
128-
}
129-
};
130-
131-
if item_tree.data.is_empty()
132-
&& item_tree.top_level.is_empty()
133-
&& item_tree.attrs.is_empty()
134-
&& item_tree.top_attrs.is_empty()
135-
{
136-
EMPTY
137-
.get_or_init(|| {
138-
Arc::new(ItemTree {
139-
top_level: Box::new([]),
140-
attrs: FxHashMap::default(),
141-
data: FxHashMap::default(),
142-
top_attrs: RawAttrs::EMPTY,
143-
vis: ItemVisibilities { arena: Box::new([]) },
144-
})
145-
})
146-
.clone()
147-
} else {
148-
item_tree.shrink_to_fit();
149-
Arc::new(item_tree)
150-
}
151-
}
152-
153-
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
154-
let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
155-
static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
156-
157-
let loc = block.lookup(db);
158-
let block = loc.ast_id.to_node(db);
159-
160-
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
161-
let mut item_tree = ctx.lower_block(&block);
162-
if item_tree.data.is_empty()
163-
&& item_tree.top_level.is_empty()
164-
&& item_tree.attrs.is_empty()
165-
&& item_tree.top_attrs.is_empty()
166-
{
167-
EMPTY
168-
.get_or_init(|| {
169-
Arc::new(ItemTree {
170-
top_level: Box::new([]),
171-
attrs: FxHashMap::default(),
172-
data: FxHashMap::default(),
173-
top_attrs: RawAttrs::EMPTY,
174-
vis: ItemVisibilities { arena: Box::new([]) },
175-
})
176-
})
177-
.clone()
178-
} else {
179-
item_tree.shrink_to_fit();
180-
Arc::new(item_tree)
181-
}
182-
}
183-
184168
/// Returns an iterator over all items located at the top level of the `HirFileId` this
185169
/// `ItemTree` was created from.
186170
pub(crate) fn top_level_items(&self) -> &[ModItemId] {
@@ -297,10 +281,10 @@ impl TreeId {
297281
Self { file, block }
298282
}
299283

300-
pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
284+
pub(crate) fn item_tree<'db>(&self, db: &'db dyn DefDatabase) -> &'db ItemTree {
301285
match self.block {
302-
Some(block) => db.block_item_tree(block),
303-
None => db.file_item_tree(self.file),
286+
Some(block) => block_item_tree_query(db, block),
287+
None => file_item_tree_query(db, self.file),
304288
}
305289
}
306290

src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl DefCollector<'_> {
357357
macro_depth: 0,
358358
module_id: DefMap::ROOT,
359359
tree_id: TreeId::new(file_id.into(), None),
360-
item_tree: &item_tree,
360+
item_tree,
361361
mod_dir: ModDir::root(),
362362
}
363363
.collect_in_top_module(item_tree.top_level_items());
@@ -378,7 +378,7 @@ impl DefCollector<'_> {
378378
macro_depth: 0,
379379
module_id: DefMap::ROOT,
380380
tree_id,
381-
item_tree: &item_tree,
381+
item_tree,
382382
mod_dir: ModDir::root(),
383383
}
384384
.collect_in_top_module(item_tree.top_level_items());
@@ -1381,7 +1381,7 @@ impl DefCollector<'_> {
13811381
macro_depth: directive.depth,
13821382
module_id: directive.module_id,
13831383
tree_id: *tree,
1384-
item_tree: &item_tree,
1384+
item_tree,
13851385
mod_dir,
13861386
}
13871387
.collect(&[*mod_item], directive.container);
@@ -1570,7 +1570,7 @@ impl DefCollector<'_> {
15701570
macro_depth: depth,
15711571
tree_id: TreeId::new(file_id, None),
15721572
module_id,
1573-
item_tree: &item_tree,
1573+
item_tree,
15741574
mod_dir,
15751575
}
15761576
.collect(item_tree.top_level_items(), container);
@@ -2142,7 +2142,7 @@ impl ModCollector<'_, '_> {
21422142
macro_depth: self.macro_depth,
21432143
module_id,
21442144
tree_id: TreeId::new(file_id.into(), None),
2145-
item_tree: &item_tree,
2145+
item_tree,
21462146
mod_dir,
21472147
}
21482148
.collect_in_top_module(item_tree.top_level_items());

0 commit comments

Comments
 (0)